--- truecrypt/common/crypto.c 2018/04/24 16:42:57 1.1.1.7 +++ truecrypt/common/crypto.c 2018/04/24 16:53:59 1.1.1.15 @@ -1,20 +1,24 @@ -/* Legal Notice: The source code contained in this file has been derived from - the source code of Encryption for the Masses 2.02a, which is Copyright (c) - 1998-99 Paul Le Roux and which is covered by the 'License Agreement for - Encryption for the Masses'. Modifications and additions to that source code - contained in this file are Copyright (c) 2004-2005 TrueCrypt Foundation and - Copyright (c) 2004 TrueCrypt Team, and are covered by TrueCrypt License 2.0 - the full text of which is contained in the file License.txt included in - TrueCrypt binary and source code distribution archives. */ +/* + Legal Notice: Some portions of the source code contained in this file were + derived 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 all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.5 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ #include "Tcdefs.h" #include "Crypto.h" +#include "Xts.h" #include "Crc.h" -#include "Endian.h" - -#ifdef LINUX_DRIVER -#include +#include "Common/Endian.h" +#include +#ifndef TC_WINDOWS_BOOT +#include "EncryptionThreadPool.h" #endif +#include "Volumes.h" /* Update the following when adding a new cipher or EA: @@ -31,64 +35,119 @@ */ +#ifndef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + // Cipher configuration static Cipher Ciphers[] = { // Block Size Key Size Key Schedule Size // ID Name (Bytes) (Bytes) (Bytes) - { AES, "AES", 16, 32, sizeof(aes_encrypt_ctx)+sizeof(aes_decrypt_ctx) }, - { BLOWFISH, "Blowfish", 8, 56, 4168 }, - { CAST, "CAST5", 8, 16, 128 }, - { DES56, "DES", 8, 7, 128 }, - { SERPENT, "Serpent", 16, 32, 140*4 }, - { TRIPLEDES,"Triple DES", 8, 8*3, 128*3 }, - { TWOFISH, "Twofish", 16, 32, TWOFISH_KS }, - { 0, 0, 0, 0, 0 } + { AES, "AES", 16, 32, AES_KS }, + { SERPENT, "Serpent", 16, 32, 140*4 }, + { TWOFISH, "Twofish", 16, 32, TWOFISH_KS }, +#ifndef TC_WINDOWS_BOOT + { BLOWFISH, "Blowfish", 8, 56, 4168 }, // Deprecated/legacy + { CAST, "CAST5", 8, 16, 128 }, // Deprecated/legacy + { DES56, "DES", 8, 7, 128 }, // Deprecated/legacy + { TRIPLEDES,"Triple DES", 8, 8*3, 128*3 }, // Deprecated/legacy +#endif + { 0, 0, 0, 0, 0 } }; + // Encryption algorithm configuration +// The following modes have been deprecated (legacy): LRW, CBC, INNER_CBC, OUTER_CBC static EncryptionAlgorithm EncryptionAlgorithms[] = { - // Cipher(s) Mode - { { 0, 0 } , 0 }, // (must be null) - { { AES, 0 } , CBC }, // AES - { { BLOWFISH, 0 } , CBC }, // Blowfish - { { CAST, 0 } , CBC }, // CAST5 - { { SERPENT, 0 } , CBC }, // Serpent - { { TRIPLEDES, 0 } , CBC }, // Triple DES - { { TWOFISH, 0 } , CBC }, // Twofish - { { BLOWFISH, AES, 0 } , INNER_CBC }, // AES-Blowfish - { { SERPENT, BLOWFISH, AES, 0 } , INNER_CBC }, // AES-Blowfish-Serpent - { { TWOFISH, AES, 0 } , OUTER_CBC }, // AES-Twofish - { { SERPENT, TWOFISH, AES, 0 } , OUTER_CBC }, // AES-Twofish-Serpent - { { AES, SERPENT, 0 } , OUTER_CBC }, // Serpent-AES - { { AES, TWOFISH, SERPENT, 0 } , OUTER_CBC }, // Serpent-Twofish-AES - { { SERPENT, TWOFISH, 0 } , OUTER_CBC }, // Twofish-Serpent - { { 0, 0 } , 0 } // (must be null) + // Cipher(s) Modes FormatEnabled + +#ifndef TC_WINDOWS_BOOT + + { { 0, 0 }, { 0, 0, 0, 0 }, 0 }, // Must be all-zero + { { AES, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { SERPENT, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { TWOFISH, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { TWOFISH, AES, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { SERPENT, TWOFISH, AES, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { AES, SERPENT, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { AES, TWOFISH, SERPENT, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { SERPENT, TWOFISH, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { BLOWFISH, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { CAST, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { TRIPLEDES, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { BLOWFISH, AES, 0 }, { INNER_CBC, 0, 0, 0 }, 0 }, // Deprecated/legacy + { { SERPENT, BLOWFISH, AES, 0 }, { INNER_CBC, 0, 0, 0 }, 0 }, // Deprecated/legacy + { { 0, 0 }, { 0, 0, 0, 0 }, 0 } // Must be all-zero + +#else // TC_WINDOWS_BOOT + + // Encryption algorithms available for boot drive encryption + { { 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 + +#endif + +}; + + + +// 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 }, + { SHA1, "SHA-1", TRUE, FALSE }, // Deprecated/legacy +#endif + { 0, 0, 0 } }; /* Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) */ -int CipherInit (int cipher, unsigned char *key, unsigned char *ks) +int CipherInit (int cipher, unsigned char *key, unsigned __int8 *ks) { - int retVal = 0; + int retVal = ERR_SUCCESS; switch (cipher) { - case BLOWFISH: - BF_set_key ((BF_KEY *)ks, CipherGetKeySize(BLOWFISH), key); - break; - case AES: - if (aes_encrypt_key(key, CipherGetKeySize(AES), (aes_encrypt_ctx *) ks) != aes_good) +#ifndef TC_WINDOWS_BOOT + if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) return ERR_CIPHER_INIT_FAILURE; - if (aes_decrypt_key(key, CipherGetKeySize(AES), (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx))) != aes_good) + if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx))) != EXIT_SUCCESS) return ERR_CIPHER_INIT_FAILURE; +#else + if (aes_set_key (key, (length_type) CipherGetKeySize(AES), (aes_context *) ks) != 0) + return ERR_CIPHER_INIT_FAILURE; +#endif + break; + + case SERPENT: + serpent_set_key (key, CipherGetKeySize(SERPENT) * 8, ks); + break; + + case TWOFISH: + twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, CipherGetKeySize(TWOFISH) * 8); + break; +#ifndef TC_WINDOWS_BOOT + + case BLOWFISH: + /* Deprecated/legacy */ + BF_set_key ((BF_KEY *)ks, CipherGetKeySize(BLOWFISH), key); break; case DES56: - /* Included for testing purposes only */ + /* Deprecated/legacy */ switch (des_key_sched ((des_cblock *) key, (struct des_ks_struct *) ks)) { case -1: @@ -100,14 +159,12 @@ int CipherInit (int cipher, unsigned cha break; case CAST: + /* Deprecated/legacy */ CAST_set_key((CAST_KEY *) ks, CipherGetKeySize(CAST), key); break; - case SERPENT: - serpent_set_key (key, CipherGetKeySize(SERPENT) * 8, ks); - break; - case TRIPLEDES: + /* Deprecated/legacy */ switch (des_key_sched ((des_cblock *) key, (struct des_ks_struct *) ks)) { case -1: @@ -132,13 +189,22 @@ int CipherInit (int cipher, unsigned cha retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error break; } - break; - case TWOFISH: - twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, CipherGetKeySize(TWOFISH) * 8); + // Verify whether all three DES keys are mutually different + if (((*((__int64 *) key) ^ *((__int64 *) key+1)) & 0xFEFEFEFEFEFEFEFEULL) == 0 + || ((*((__int64 *) key+1) ^ *((__int64 *) key+2)) & 0xFEFEFEFEFEFEFEFEULL) == 0 + || ((*((__int64 *) key) ^ *((__int64 *) key+2)) & 0xFEFEFEFEFEFEFEFEULL) == 0) + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + break; +#endif // TC_WINDOWS_BOOT + + default: + // Unknown/wrong cipher ID + return ERR_CIPHER_INIT_FAILURE; } + return retVal; } @@ -146,14 +212,17 @@ void EncipherBlock(int cipher, void *dat { switch (cipher) { - case BLOWFISH: BF_ecb_le_encrypt (data, data, ks, 1); break; case AES: aes_encrypt (data, data, ks); break; - case DES56: des_encrypt (data, ks, 1); break; - case CAST: CAST_ecb_encrypt (data, data, ks, 1); break; + case TWOFISH: twofish_encrypt (ks, data, data); break; case SERPENT: serpent_encrypt (data, data, ks); break; - case TRIPLEDES: des_ecb3_encrypt (data, data, ks, +#ifndef TC_WINDOWS_BOOT + case BLOWFISH: BF_ecb_le_encrypt (data, data, ks, 1); break; // Deprecated/legacy + case DES56: des_encrypt (data, ks, 1); break; // Deprecated/legacy + case CAST: CAST_ecb_encrypt (data, data, ks, 1); break; // Deprecated/legacy + case TRIPLEDES: des_ecb3_encrypt (data, data, ks, // Deprecated/legacy (void*)((char*) ks + CipherGetKeyScheduleSize (DES56)), (void*)((char*) ks + CipherGetKeyScheduleSize (DES56) * 2), 1); break; - case TWOFISH: twofish_encrypt (ks, data, data); break; +#endif + default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID } } @@ -161,15 +230,20 @@ void DecipherBlock(int cipher, void *dat { switch (cipher) { - case BLOWFISH: BF_ecb_le_encrypt (data, data, ks, 0); break; - case AES: aes_decrypt (data, data, (void *) ((char *) ks + sizeof(aes_encrypt_ctx))); break; - case DES56: des_encrypt (data, ks, 0); break; - case CAST: CAST_ecb_encrypt (data, data, ks,0); break; case SERPENT: serpent_decrypt (data, data, ks); break; - case TRIPLEDES: des_ecb3_encrypt (data, data, ks, + case TWOFISH: twofish_decrypt (ks, data, data); break; +#ifndef TC_WINDOWS_BOOT + case AES: aes_decrypt (data, data, (void *) ((char *) ks + sizeof(aes_encrypt_ctx))); break; + case BLOWFISH: BF_ecb_le_encrypt (data, data, ks, 0); break; // Deprecated/legacy + case DES56: des_encrypt (data, ks, 0); break; // Deprecated/legacy + case CAST: CAST_ecb_encrypt (data, data, ks,0); break; // Deprecated/legacy + case TRIPLEDES: des_ecb3_encrypt (data, data, ks, // Deprecated/legacy (void*)((char*) ks + CipherGetKeyScheduleSize (DES56)), (void*)((char*) ks + CipherGetKeyScheduleSize (DES56) * 2), 0); break; - case TWOFISH: twofish_decrypt (ks, data, data); break; +#else + case AES: aes_decrypt (data, data, ks); break; +#endif + default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID } } @@ -182,7 +256,7 @@ Cipher *CipherGet (int id) if (Ciphers[i].Id == id) return &Ciphers[i]; - return 0; + return NULL; } char *CipherGetName (int cipherId) @@ -232,10 +306,14 @@ int EAGetNext (int previousEA) return 0; } -/* Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) */ -int EAInit (int ea, unsigned char *key, unsigned char *ks) + +// Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) +int EAInit (int ea, unsigned char *key, unsigned __int8 *ks) { - int c, retVal = 0; + int c, retVal = ERR_SUCCESS; + + if (ea == 0) + return ERR_CIPHER_INIT_FAILURE; for (c = EAGetFirstCipher (ea); c != 0; c = EAGetNextCipher (ea, c)) { @@ -255,11 +333,60 @@ int EAInit (int ea, unsigned char *key, return retVal; } + +#ifndef TC_WINDOWS_BOOT + +BOOL EAInitMode (PCRYPTO_INFO ci) +{ + switch (ci->mode) + { + case XTS: + // Secondary key schedule + if (EAInit (ci->ea, ci->k2, ci->ks2) != ERR_SUCCESS) + return FALSE; + + /* 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 + that the size of each of the volumes is 1024 terabytes). */ + break; + + case LRW: + switch (CipherGetBlockSize (EAGetFirstCipher (ci->ea))) + { + case 8: + /* Deprecated/legacy */ + return Gf64TabInit (ci->k2, &ci->gf_ctx); + + case 16: + return Gf128Tab64Init (ci->k2, &ci->gf_ctx); + + default: + TC_THROW_FATAL_EXCEPTION; + } + + break; + + case CBC: + case INNER_CBC: + case OUTER_CBC: + // The mode does not need to be initialized or is initialized elsewhere + return TRUE; + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } + return TRUE; +} + + // Returns name of EA, cascaded cipher names are separated by hyphens char *EAGetName (char *buf, int ea) { int i = EAGetLastCipher(ea); - strcpy (buf, CipherGetName (i)); + strcpy (buf, (i != 0) ? CipherGetName (i) : "?"); while (i = EAGetPreviousCipher(ea, i)) { @@ -270,13 +397,32 @@ char *EAGetName (char *buf, int ea) return buf; } -// Returns sum of key sizes of all EA ciphers + +int EAGetByName (char *name) +{ + int ea = EAGetFirst (); + char n[128]; + + do + { + EAGetName (n, ea); + if (strcmp (n, name) == 0) + return ea; + } + while (ea = EAGetNext (ea)); + + return 0; +} + +#endif // TC_WINDOWS_BOOT + +// Returns sum of key sizes of all ciphers of the EA (in bytes) int EAGetKeySize (int ea) { - int i = EAGetFirstCipher(ea); + int i = EAGetFirstCipher (ea); int size = CipherGetKeySize (i); - while (i = EAGetNextCipher(ea, i)) + while (i = EAGetNextCipher (ea, i)) { size += CipherGetKeySize (i); } @@ -284,19 +430,48 @@ int EAGetKeySize (int ea) return size; } -// Returns the mode of operation of the whole EA -int EAGetMode (int ea) + +// Returns the first mode of operation of EA +int EAGetFirstMode (int ea) { - return (EncryptionAlgorithms[ea].Mode); + return (EncryptionAlgorithms[ea].Modes[0]); +} + + +int EAGetNextMode (int ea, int previousModeId) +{ + int c, i = 0; + while (c = EncryptionAlgorithms[ea].Modes[i++]) + { + if (c == previousModeId) + return EncryptionAlgorithms[ea].Modes[i]; + } + + return 0; } + +#ifndef TC_WINDOWS_BOOT + // Returns the name of the mode of operation of the whole EA -char *EAGetModeName (int ea, BOOL capitalLetters) +char *EAGetModeName (int ea, int mode, BOOL capitalLetters) { - switch (EncryptionAlgorithms[ea].Mode) + switch (mode) { + case XTS: + + return "XTS"; + + case LRW: + + /* Deprecated/legacy */ + + return "LRW"; + case CBC: { + /* Deprecated/legacy */ + char eaName[100]; EAGetName (eaName, ea); @@ -307,16 +482,25 @@ char *EAGetModeName (int ea, BOOL capita } case OUTER_CBC: + + /* Deprecated/legacy */ + return capitalLetters ? "Outer-CBC" : "outer-CBC"; case INNER_CBC: + + /* Deprecated/legacy */ + return capitalLetters ? "Inner-CBC" : "inner-CBC"; } return "[unknown]"; } -// Returns sum of key schedule sizes of all EA ciphers +#endif // TC_WINDOWS_BOOT + + +// Returns sum of key schedule sizes of all ciphers of the EA int EAGetKeyScheduleSize (int ea) { int i = EAGetFirstCipher(ea); @@ -330,12 +514,30 @@ int EAGetKeyScheduleSize (int ea) return size; } -// Returns largest key needed by all EAs + +// Returns the largest key size needed by an EA for the specified mode of operation +int EAGetLargestKeyForMode (int mode) +{ + int ea, key = 0; + + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + if (!EAIsModeSupported (ea, mode)) + continue; + + if (EAGetKeySize (ea) >= key) + key = EAGetKeySize (ea); + } + return key; +} + + +// Returns the largest key needed by any EA for any mode int EAGetLargestKey () { int ea, key = 0; - for (ea = EAGetFirst (); ea != 0 ; ea = EAGetNext (ea)) + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) { if (EAGetKeySize (ea) >= key) key = EAGetKeySize (ea); @@ -344,6 +546,7 @@ int EAGetLargestKey () return key; } + // Returns number of ciphers in EA int EAGetCipherCount (int ea) { @@ -359,6 +562,7 @@ int EAGetFirstCipher (int ea) return EncryptionAlgorithms[ea].Ciphers[0]; } + int EAGetLastCipher (int ea) { int c, i = 0; @@ -367,6 +571,7 @@ int EAGetLastCipher (int ea) return EncryptionAlgorithms[ea].Ciphers[i - 2]; } + int EAGetNextCipher (int ea, int previousCipherId) { int c, i = 0; @@ -379,6 +584,7 @@ int EAGetNextCipher (int ea, int previou return 0; } + int EAGetPreviousCipher (int ea, int previousCipherId) { int c, i = 0; @@ -395,80 +601,354 @@ int EAGetPreviousCipher (int ea, int pre return 0; } -char *get_hash_algo_name (int hash_algo_id) + +int EAIsFormatEnabled (int ea) +{ + return EncryptionAlgorithms[ea].FormatEnabled; +} + + +// Returns TRUE if the mode of operation is supported for the encryption algorithm +BOOL EAIsModeSupported (int ea, int testedMode) { - switch (hash_algo_id) + int mode; + + for (mode = EAGetFirstMode (ea); mode != 0; mode = EAGetNextMode (ea, mode)) { - case SHA1: return "SHA-1"; - case RIPEMD160: return "RIPEMD-160"; - case WHIRLPOOL: return "Whirlpool"; - default: return "Unknown"; + if (mode == testedMode) + return TRUE; } + return FALSE; +} + + +Hash *HashGet (int id) +{ + int i; + for (i = 0; Hashes[i].Id != 0; i++) + if (Hashes[i].Id == id) + return &Hashes[i]; + + return 0; +} + + +int HashGetIdByName (char *name) +{ + int i; + for (i = 0; Hashes[i].Id != 0; i++) + if (strcmp (Hashes[i].Name, name) == 0) + return Hashes[i].Id; + + return 0; +} + + +char *HashGetName (int hashId) +{ + return HashGet (hashId) -> Name; +} + + +BOOL HashIsDeprecated (int hashId) +{ + return HashGet (hashId) -> Deprecated; } -#ifndef LINUX_DRIVER -PCRYPTO_INFO -crypto_open () +#endif // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + + +#ifdef TC_WINDOWS_BOOT + +static byte CryptoInfoBufferInUse = 0; +CRYPTO_INFO CryptoInfoBuffer; + +#endif + +PCRYPTO_INFO crypto_open () { +#ifndef TC_WINDOWS_BOOT + /* Do the crt allocation */ - PCRYPTO_INFO cryptoInfo = TCalloc (sizeof (CRYPTO_INFO)); + PCRYPTO_INFO cryptoInfo = (PCRYPTO_INFO) TCalloc (sizeof (CRYPTO_INFO)); + memset (cryptoInfo, 0, sizeof (CRYPTO_INFO)); + #ifndef DEVICE_DRIVER -#ifdef _WIN32 VirtualLock (cryptoInfo, sizeof (CRYPTO_INFO)); #endif -#endif if (cryptoInfo == NULL) return NULL; cryptoInfo->ea = -1; return cryptoInfo; + +#else // TC_WINDOWS_BOOT + +#if 0 + if (CryptoInfoBufferInUse) + TC_THROW_FATAL_EXCEPTION; +#endif + CryptoInfoBufferInUse = 1; + return &CryptoInfoBuffer; + +#endif // TC_WINDOWS_BOOT } -void -crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen) +void crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen) { keyInfo->keyLength = nUserKeyLen; burn (keyInfo->userKey, sizeof (keyInfo->userKey)); memcpy (keyInfo->userKey, lpszUserKey, nUserKeyLen); } -void -crypto_close (PCRYPTO_INFO cryptoInfo) +void crypto_close (PCRYPTO_INFO cryptoInfo) { +#ifndef TC_WINDOWS_BOOT + if (cryptoInfo != NULL) { burn (cryptoInfo, sizeof (CRYPTO_INFO)); #ifndef DEVICE_DRIVER -#ifdef _WIN32 VirtualUnlock (cryptoInfo, sizeof (CRYPTO_INFO)); #endif -#endif TCfree (cryptoInfo); } + +#else // TC_WINDOWS_BOOT + + burn (&CryptoInfoBuffer, sizeof (CryptoInfoBuffer)); + CryptoInfoBufferInUse = FALSE; + +#endif // TC_WINDOWS_BOOT +} + + +#ifndef TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + + +#ifndef TC_NO_COMPILER_INT64 +void Xor128 (unsigned __int64 *a, unsigned __int64 *b) +{ + *a++ ^= *b++; + *a ^= *b; +} + + +void Xor64 (unsigned __int64 *a, unsigned __int64 *b) +{ + *a ^= *b; +} + + +void EncryptBufferLRW128 (unsigned __int8 *buffer, unsigned __int64 length, unsigned __int64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + int cipherCount = EAGetCipherCount (cryptoInfo->ea); + unsigned __int8 *p = buffer; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[16]; + unsigned __int64 b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + if (length % 16) + TC_THROW_FATAL_EXCEPTION; + + // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). + + for (b = 0; b < length >> 4; b++) + { + Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); + Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + if (cipherCount > 1) + { + // Cipher cascade + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncipherBlock (cipher, p, ks); + ks += CipherGetKeyScheduleSize (cipher); + } + ks = cryptoInfo->ks; + } + else + { + EncipherBlock (cipher, p, ks); + } + + Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + p += 16; + + if (i[7] != 0xff) + i[7]++; + else + *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + +void EncryptBufferLRW64 (unsigned __int8 *buffer, unsigned __int64 length, unsigned __int64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + unsigned __int8 *p = buffer; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[8]; + unsigned __int64 b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + if (length % 8) + TC_THROW_FATAL_EXCEPTION; + + for (b = 0; b < length >> 3; b++) + { + Gf64MulTab (i, t, &cryptoInfo->gf_ctx); + Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + EncipherBlock (cipher, p, ks); + + Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + p += 8; + + if (i[7] != 0xff) + i[7]++; + else + *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + +void DecryptBufferLRW128 (unsigned __int8 *buffer, unsigned __int64 length, unsigned __int64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + int cipherCount = EAGetCipherCount (cryptoInfo->ea); + unsigned __int8 *p = buffer; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[16]; + unsigned __int64 b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + if (length % 16) + TC_THROW_FATAL_EXCEPTION; + + // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). + + for (b = 0; b < length >> 4; b++) + { + Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); + Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + if (cipherCount > 1) + { + // Cipher cascade + ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + DecipherBlock (cipher, p, ks); + } + } + else + { + DecipherBlock (cipher, p, ks); + } + + Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + p += 16; + + if (i[7] != 0xff) + i[7]++; + else + *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + + +void DecryptBufferLRW64 (unsigned __int8 *buffer, unsigned __int64 length, unsigned __int64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + unsigned __int8 *p = buffer; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[8]; + unsigned __int64 b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + if (length % 8) + TC_THROW_FATAL_EXCEPTION; + + for (b = 0; b < length >> 3; b++) + { + Gf64MulTab (i, t, &cryptoInfo->gf_ctx); + Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + DecipherBlock (cipher, p, ks); + + Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t); + + p += 8; + + if (i[7] != 0xff) + i[7]++; + else + *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); } - -#endif // LINUX_DRIVER -// Initializes IV and whitening values for sector encryption/decryption +// Initializes IV and whitening values for sector encryption/decryption in CBC mode. +// IMPORTANT: This function has been deprecated (legacy). static void -InitSectorIVAndWhitening (unsigned __int64 secNo, +InitSectorIVAndWhitening (unsigned __int64 unitNo, int blockSize, unsigned __int32 *iv, unsigned __int64 *ivSeed, unsigned __int32 *whitening) { + + /* IMPORTANT: This function has been deprecated (legacy) */ + unsigned __int64 iv64[4]; unsigned __int32 *iv32 = (unsigned __int32 *) iv64; - iv64[0] = ivSeed[0] ^ LE64(secNo); - iv64[1] = ivSeed[1] ^ LE64(secNo); - iv64[2] = ivSeed[2] ^ LE64(secNo); + iv64[0] = ivSeed[0] ^ LE64(unitNo); + iv64[1] = ivSeed[1] ^ LE64(unitNo); + iv64[2] = ivSeed[2] ^ LE64(unitNo); if (blockSize == 16) { - iv64[3] = ivSeed[3] ^ LE64(secNo); + iv64[3] = ivSeed[3] ^ LE64(unitNo); } iv[0] = iv32[0]; @@ -494,11 +974,14 @@ InitSectorIVAndWhitening (unsigned __int whitening[0] = LE32( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) ); whitening[1] = LE32( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) ); break; + + default: + TC_THROW_FATAL_EXCEPTION; } } -// EncryptBufferCBC +// EncryptBufferCBC (deprecated/legacy) // // data: data to be encrypted // len: number of bytes to encrypt (must be divisible by the largest cipher block size) @@ -511,16 +994,21 @@ InitSectorIVAndWhitening (unsigned __int static void EncryptBufferCBC (unsigned __int32 *data, unsigned int len, - unsigned char *ks, + unsigned __int8 *ks, unsigned __int32 *iv, unsigned __int32 *whitening, int ea, int cipher) { + /* IMPORTANT: This function has been deprecated (legacy) */ + unsigned __int32 bufIV[4]; unsigned __int64 i; int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); + if (len % blockSize) + TC_THROW_FATAL_EXCEPTION; + // IV bufIV[0] = iv[0]; bufIV[1] = iv[1]; @@ -581,7 +1069,7 @@ EncryptBufferCBC (unsigned __int32 *data } -// DecryptBufferCBC +// DecryptBufferCBC (deprecated/legacy) // // data: data to be decrypted // len: number of bytes to decrypt (must be divisible by the largest cipher block size) @@ -594,17 +1082,23 @@ EncryptBufferCBC (unsigned __int32 *data static void DecryptBufferCBC (unsigned __int32 *data, unsigned int len, - unsigned char *ks, + unsigned __int8 *ks, unsigned __int32 *iv, unsigned __int32 *whitening, int ea, int cipher) { + + /* IMPORTANT: This function has been deprecated (legacy) */ + unsigned __int32 bufIV[4]; unsigned __int64 i; unsigned __int32 ct[4]; int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); + if (len % blockSize) + TC_THROW_FATAL_EXCEPTION; + // IV bufIV[0] = iv[0]; bufIV[1] = iv[1]; @@ -667,6 +1161,7 @@ DecryptBufferCBC (unsigned __int32 *data data += blockSize / sizeof(*data); } } +#endif // #ifndef TC_NO_COMPILER_INT64 // EncryptBuffer @@ -674,90 +1169,212 @@ DecryptBufferCBC (unsigned __int32 *data // buf: data to be encrypted // 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) -// ks: scheduled key -// iv: IV -// whitening: whitening constants -// ea: encryption algorithm - -void -EncryptBuffer (unsigned __int32 *buf, - unsigned __int64 len, - unsigned char *ks, - void *iv, - void *whitening, - int ea) +void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) { - int cipher; - - switch (EAGetMode(ea)) + switch (cryptoInfo->mode) { - case CBC: - case INNER_CBC: + case XTS: + { + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 *ks2 = cryptoInfo->ks2; + UINT64_STRUCT dataUnitNo; + int cipher; + + // When encrypting/decrypting a buffer (typically a volume header) the sequential number + // of the first XTS data unit in the buffer is always 0 and the start of the buffer is + // always considered aligned with the start of a data unit. + dataUnitNo.LowPart = 0; + dataUnitNo.HighPart = 0; + + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); - for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) + ks += CipherGetKeyScheduleSize (cipher); + ks2 += CipherGetKeyScheduleSize (cipher); + } + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) { - EncryptBufferCBC (buf, - (unsigned int) len, - ks, - (unsigned __int32 *) iv, - (unsigned __int32 *) whitening, - 0, - cipher); + case 8: + EncryptBufferLRW64 ((unsigned __int8 *)buf, (unsigned __int64) len, 1, cryptoInfo); + break; - ks += CipherGetKeyScheduleSize (cipher); + case 16: + EncryptBufferLRW128 ((unsigned __int8 *)buf, (unsigned __int64) len, 1, cryptoInfo); + break; + + default: + TC_THROW_FATAL_EXCEPTION; } + break; + case CBC: + case INNER_CBC: + { + /* Deprecated/legacy */ + + unsigned __int8 *ks = cryptoInfo->ks; + int cipher; + + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncryptBufferCBC ((unsigned __int32 *) buf, + (unsigned int) len, + ks, + (unsigned __int32 *) cryptoInfo->k2, + (unsigned __int32 *) &cryptoInfo->k2[8], + 0, + cipher); + + ks += CipherGetKeyScheduleSize (cipher); + } + } break; case OUTER_CBC: - EncryptBufferCBC (buf, + /* Deprecated/legacy */ + + EncryptBufferCBC ((unsigned __int32 *) buf, (unsigned int) len, - ks, - (unsigned __int32 *) iv, - (unsigned __int32 *) whitening, - ea, + cryptoInfo->ks, + (unsigned __int32 *) cryptoInfo->k2, + (unsigned __int32 *) &cryptoInfo->k2[8], + cryptoInfo->ea, 0); break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; } } -// EncryptSectors -// +#ifndef TC_NO_COMPILER_INT64 +// Converts a data unit number to the index of the first LRW block in the data unit. +// Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). +unsigned __int64 DataUnit2LRWIndex (unsigned __int64 dataUnit, int blockSize, PCRYPTO_INFO ci) +{ + /* Deprecated/legacy */ + + if (ci->hiddenVolume) + dataUnit -= ci->hiddenVolumeOffset / ENCRYPTION_DATA_UNIT_SIZE; + else + dataUnit -= TC_VOLUME_HEADER_SIZE_LEGACY / ENCRYPTION_DATA_UNIT_SIZE; // Compensate for the volume header size + + switch (blockSize) + { + case 8: + return (dataUnit << 6) | 1; + + case 16: + return (dataUnit << 5) | 1; + + default: + TC_THROW_FATAL_EXCEPTION; + } + + return 0; +} +#endif // #ifndef TC_NO_COMPILER_INT64 + + // buf: data to be encrypted -// secNo: sector number relative to volume start -// noSectors: number of sectors in buffer -// ks: scheduled key -// iv: IV -// ea: encryption algorithm +// 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, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +#ifndef TC_WINDOWS_BOOT +{ + EncryptionThreadPoolDoWork (EncryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci); +} -void _cdecl -EncryptSectors (unsigned __int32 *buf, - unsigned __int64 secNo, - unsigned __int64 noSectors, - unsigned char *ks, - void *iv, - int ea) -{ - unsigned __int64 *iv64 = (unsigned __int64 *) iv; - unsigned __int32 sectorIV[4]; - unsigned __int32 secWhitening[2]; +void EncryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +#endif // !TC_WINDOWS_BOOT +{ + int ea = ci->ea; + unsigned __int8 *ks = ci->ks; + unsigned __int8 *ks2 = ci->ks2; int cipher; - switch (EAGetMode(ea)) +#ifndef TC_NO_COMPILER_INT64 + void *iv = ci->k2; // Deprecated/legacy + unsigned __int64 unitNo = structUnitNo->Value; + unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy + unsigned __int32 sectorIV[4]; // Deprecated/legacy + unsigned __int32 secWhitening[2]; // Deprecated/legacy +#endif + + switch (ci->mode) { + case XTS: + for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) + { + EncryptBufferXTS (buf, + nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + structUnitNo, + 0, + ks, + ks2, + cipher); + + ks += CipherGetKeyScheduleSize (cipher); + ks2 += CipherGetKeyScheduleSize (cipher); + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (ea))) + { + case 8: + EncryptBufferLRW64 (buf, + (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + DataUnit2LRWIndex (unitNo, 8, ci), + ci); + break; + + case 16: + EncryptBufferLRW128 (buf, + (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + DataUnit2LRWIndex (unitNo, 16, ci), + ci); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + case CBC: case INNER_CBC: - while (noSectors--) + /* Deprecated/legacy */ + + while (nbrUnits--) { for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) { - InitSectorIVAndWhitening (secNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); + InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); - EncryptBufferCBC (buf, - SECTOR_SIZE, + EncryptBufferCBC ((unsigned __int32 *) buf, + ENCRYPTION_DATA_UNIT_SIZE, ks, sectorIV, secWhitening, @@ -767,29 +1384,36 @@ EncryptSectors (unsigned __int32 *buf, ks += CipherGetKeyScheduleSize (cipher); } ks -= EAGetKeyScheduleSize (ea); - buf += SECTOR_SIZE / sizeof(*buf); - secNo++; + buf += ENCRYPTION_DATA_UNIT_SIZE; + unitNo++; } break; case OUTER_CBC: - while (noSectors--) + /* Deprecated/legacy */ + + while (nbrUnits--) { - InitSectorIVAndWhitening (secNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); + InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); - EncryptBufferCBC (buf, - SECTOR_SIZE, + EncryptBufferCBC ((unsigned __int32 *) buf, + ENCRYPTION_DATA_UNIT_SIZE, ks, sectorIV, secWhitening, ea, 0); - buf += SECTOR_SIZE / sizeof(*buf); - secNo++; + buf += ENCRYPTION_DATA_UNIT_SIZE; + unitNo++; } break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; } } @@ -798,121 +1422,337 @@ EncryptSectors (unsigned __int32 *buf, // buf: data to be decrypted // 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) -// ks: scheduled key -// iv: IV -// whitening: whitening constants -// ea: encryption algorithm -void -DecryptBuffer (unsigned __int32 *buf, - unsigned __int64 len, - unsigned char *ks, - void *iv, - void *whitening, - int ea) +void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) { - int cipher; - - switch (EAGetMode(ea)) + switch (cryptoInfo->mode) { + case XTS: + { + unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + unsigned __int8 *ks2 = cryptoInfo->ks2 + EAGetKeyScheduleSize (cryptoInfo->ea); + UINT64_STRUCT dataUnitNo; + int cipher; + + // When encrypting/decrypting a buffer (typically a volume header) the sequential number + // of the first XTS data unit in the buffer is always 0 and the start of the buffer is + // always considered aligned with the start of the data unit 0. + dataUnitNo.LowPart = 0; + dataUnitNo.HighPart = 0; + + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + ks2 -= CipherGetKeyScheduleSize (cipher); + + DecryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); + } + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) + { + case 8: + DecryptBufferLRW64 (buf, (unsigned __int64) len, 1, cryptoInfo); + break; + + case 16: + DecryptBufferLRW128 (buf, (unsigned __int64) len, 1, cryptoInfo); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + case CBC: case INNER_CBC: - - ks += EAGetKeyScheduleSize (ea); - for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) { - ks -= CipherGetKeyScheduleSize (cipher); + /* Deprecated/legacy */ - DecryptBufferCBC (buf, - (unsigned int) len, - ks, - (unsigned __int32 *) iv, - (unsigned __int32 *) whitening, - 0, - cipher); + unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + int cipher; + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + + DecryptBufferCBC ((unsigned __int32 *) buf, + (unsigned int) len, + ks, + (unsigned __int32 *) cryptoInfo->k2, + (unsigned __int32 *) &cryptoInfo->k2[8], + 0, + cipher); + } } break; case OUTER_CBC: - DecryptBufferCBC (buf, + /* Deprecated/legacy */ + + DecryptBufferCBC ((unsigned __int32 *) buf, (unsigned int) len, - ks, - (unsigned __int32 *) iv, - (unsigned __int32 *) whitening, - ea, + cryptoInfo->ks, + (unsigned __int32 *) cryptoInfo->k2, + (unsigned __int32 *) &cryptoInfo->k2[8], + cryptoInfo->ea, 0); break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; } } -// DecryptSectors -// // buf: data to be decrypted -// secNo: sector number relative to volume start -// noSectors: number of sectors in buffer -// ks: scheduled key -// iv: IV -// ea: encryption algorithm +// 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, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +#ifndef TC_WINDOWS_BOOT +{ + EncryptionThreadPoolDoWork (DecryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci); +} -void _cdecl -DecryptSectors (unsigned __int32 *buf, - unsigned __int64 secNo, - unsigned __int64 noSectors, - unsigned char *ks, - void *iv, - int ea) -{ - unsigned __int64 *iv64 = (unsigned __int64 *) iv; - unsigned __int32 sectorIV[4]; - unsigned __int32 secWhitening[2]; +void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +#endif // !TC_WINDOWS_BOOT +{ + int ea = ci->ea; + unsigned __int8 *ks = ci->ks; + unsigned __int8 *ks2 = ci->ks2; int cipher; - switch (EAGetMode(ea)) +#ifndef TC_NO_COMPILER_INT64 + void *iv = ci->k2; // Deprecated/legacy + unsigned __int64 unitNo = structUnitNo->Value; + unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy + unsigned __int32 sectorIV[4]; // Deprecated/legacy + unsigned __int32 secWhitening[2]; // Deprecated/legacy +#endif // #ifndef TC_NO_COMPILER_INT64 + + + switch (ci->mode) { + case XTS: + ks += EAGetKeyScheduleSize (ea); + ks2 += EAGetKeyScheduleSize (ea); + + for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + ks2 -= CipherGetKeyScheduleSize (cipher); + + DecryptBufferXTS (buf, + nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + structUnitNo, + 0, + ks, + ks2, + cipher); + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (ea))) + { + case 8: + DecryptBufferLRW64 (buf, + (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + DataUnit2LRWIndex (unitNo, 8, ci), + ci); + break; + + case 16: + DecryptBufferLRW128 (buf, + (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, + DataUnit2LRWIndex (unitNo, 16, ci), + ci); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + case CBC: case INNER_CBC: - while (noSectors--) + /* Deprecated/legacy */ + + while (nbrUnits--) { ks += EAGetKeyScheduleSize (ea); for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) { - InitSectorIVAndWhitening (secNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); + InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); ks -= CipherGetKeyScheduleSize (cipher); - DecryptBufferCBC (buf, - SECTOR_SIZE, + DecryptBufferCBC ((unsigned __int32 *) buf, + ENCRYPTION_DATA_UNIT_SIZE, ks, sectorIV, secWhitening, 0, cipher); } - buf += SECTOR_SIZE / sizeof(*buf); - secNo++; + buf += ENCRYPTION_DATA_UNIT_SIZE; + unitNo++; } break; case OUTER_CBC: - while (noSectors--) + /* Deprecated/legacy */ + + while (nbrUnits--) { - InitSectorIVAndWhitening (secNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); + InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); - DecryptBufferCBC (buf, - SECTOR_SIZE, + DecryptBufferCBC ((unsigned __int32 *) buf, + ENCRYPTION_DATA_UNIT_SIZE, ks, sectorIV, secWhitening, ea, 0); - buf += SECTOR_SIZE / sizeof(*buf); - secNo++; + buf += ENCRYPTION_DATA_UNIT_SIZE; + unitNo++; } break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; } } + +// 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 + +#ifndef TC_WINDOWS_BOOT + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (LRW)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (CBC)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (OUTER_CBC)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (INNER_CBC)); // Deprecated/legacy +#endif + + return size; +} + + +#else // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE + + +#if !defined (TC_WINDOWS_BOOT_AES) && !defined (TC_WINDOWS_BOOT_SERPENT) && !defined (TC_WINDOWS_BOOT_TWOFISH) +#error No cipher defined +#endif + +void EncipherBlock(int cipher, void *data, void *ks) +{ +#ifdef TC_WINDOWS_BOOT_AES + 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); +#endif +} + +void DecipherBlock(int cipher, void *data, void *ks) +{ +#ifdef TC_WINDOWS_BOOT_AES + 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); +#endif +} + +int EAGetFirst () +{ + return 1; +} + +int EAGetNext (int previousEA) +{ + return 0; +} + +int EAInit (int ea, unsigned char *key, unsigned __int8 *ks) +{ +#ifdef TC_WINDOWS_BOOT_AES + + aes_init(); + + if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ks + sizeof (aes_encrypt_ctx))) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + +#elif defined (TC_WINDOWS_BOOT_SERPENT) + serpent_set_key (key, 32 * 8, ks); +#elif defined (TC_WINDOWS_BOOT_TWOFISH) + twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, 32 * 8); +#endif + return ERR_SUCCESS; +} + +int EAGetKeySize (int ea) +{ + return 32; +} + +int EAGetFirstCipher (int ea) +{ + return 1; +} + +void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) +{ + UINT64_STRUCT dataUnitNo; + dataUnitNo.LowPart = 0; dataUnitNo.HighPart = 0; + EncryptBufferXTS (buf, len, &dataUnitNo, 0, cryptoInfo->ks, cryptoInfo->ks2, 1); +} + +void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +{ + EncryptBufferXTS (buf, nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, structUnitNo, 0, ci->ks, ci->ks2, 1); +} + +void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) +{ + UINT64_STRUCT dataUnitNo; + dataUnitNo.LowPart = 0; dataUnitNo.HighPart = 0; + DecryptBufferXTS (buf, len, &dataUnitNo, 0, cryptoInfo->ks, cryptoInfo->ks2, 1); +} + +void DecryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +{ + DecryptBufferXTS (buf, nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, structUnitNo, 0, ci->ks, ci->ks2, 1); +} + +#endif // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE