--- truecrypt/common/crypto.c 2018/04/24 16:42:57 1.1.1.7 +++ truecrypt/common/crypto.c 2018/04/24 16:46:33 1.1.1.11 @@ -1,19 +1,23 @@ -/* 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: 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) + 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) TrueCrypt Foundation and are covered by the + TrueCrypt License 2.2 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 "Crc.h" -#include "Endian.h" +#include "Common/Endian.h" #ifdef LINUX_DRIVER +#include #include +#else +#include #endif /* Update the following when adding a new cipher or EA: @@ -47,30 +51,40 @@ static Cipher Ciphers[] = }; // Encryption algorithm configuration +// The following modes have been deprecated (legacy): 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 + { { 0, 0 }, { 0, 0, 0 }, 0 }, // Must be all-zero + { { AES, 0 }, { LRW, CBC, 0 }, 1 }, + { { BLOWFISH, 0 }, { LRW, CBC, 0 }, 0 }, + { { CAST, 0 }, { LRW, CBC, 0 }, 0 }, + { { SERPENT, 0 }, { LRW, CBC, 0 }, 1 }, + { { TRIPLEDES, 0 }, { LRW, CBC, 0 }, 0 }, + { { TWOFISH, 0 }, { LRW, CBC, 0 }, 1 }, + { { TWOFISH, AES, 0 }, { LRW, OUTER_CBC, 0 }, 1 }, + { { SERPENT, TWOFISH, AES, 0 }, { LRW, OUTER_CBC, 0 }, 1 }, + { { AES, SERPENT, 0 }, { LRW, OUTER_CBC, 0 }, 1 }, + { { AES, TWOFISH, SERPENT, 0 }, { LRW, OUTER_CBC, 0 }, 1 }, + { { SERPENT, TWOFISH, 0 }, { LRW, OUTER_CBC, 0 }, 1 }, + { { BLOWFISH, AES, 0 }, { INNER_CBC, 0, 0 }, 0 }, + { { SERPENT, BLOWFISH, AES, 0 }, { INNER_CBC, 0, 0 }, 0 }, + { { 0, 0 }, { 0, 0, 0 }, 0 } // Must be all-zero +}; + +// Hash algorithms +static Hash Hashes[] = +{ + { RIPEMD160, "RIPEMD-160" }, + { SHA1, "SHA-1" }, + { WHIRLPOOL, "Whirlpool" }, + { 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) { @@ -79,10 +93,10 @@ int CipherInit (int cipher, unsigned cha break; case AES: - if (aes_encrypt_key(key, CipherGetKeySize(AES), (aes_encrypt_ctx *) ks) != aes_good) + if (aes_encrypt_key(key, CipherGetKeySize(AES), (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_key(key, CipherGetKeySize(AES), (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx))) != EXIT_SUCCESS) return ERR_CIPHER_INIT_FAILURE; break; @@ -132,6 +146,13 @@ int CipherInit (int cipher, unsigned cha retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error break; } + + // 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; case TWOFISH: @@ -232,10 +253,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 +280,34 @@ int EAInit (int ea, unsigned char *key, return retVal; } + +int EAInitMode (PCRYPTO_INFO ci) +{ + switch (ci->mode) + { + case LRW: + switch (CipherGetBlockSize (EAGetFirstCipher (ci->ea))) + { + case 8: + return Gf64TabInit (ci->iv, &ci->gf_ctx); + + case 16: + return Gf128Tab64Init (ci->iv, &ci->gf_ctx); + + default: + return FALSE; + } + } + + 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 +318,31 @@ char *EAGetName (char *buf, int ea) return buf; } + +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; +} + + // Returns sum of key sizes of all EA ciphers 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 +350,39 @@ 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; +} + + // 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 LRW: + return "LRW"; + case CBC: { + /* Deprecated/legacy */ + char eaName[100]; EAGetName (eaName, ea); @@ -307,15 +393,22 @@ 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 int EAGetKeyScheduleSize (int ea) { @@ -330,6 +423,7 @@ int EAGetKeyScheduleSize (int ea) return size; } + // Returns largest key needed by all EAs int EAGetLargestKey () { @@ -344,6 +438,7 @@ int EAGetLargestKey () return key; } + // Returns number of ciphers in EA int EAGetCipherCount (int ea) { @@ -359,6 +454,7 @@ int EAGetFirstCipher (int ea) return EncryptionAlgorithms[ea].Ciphers[0]; } + int EAGetLastCipher (int ea) { int c, i = 0; @@ -367,6 +463,7 @@ int EAGetLastCipher (int ea) return EncryptionAlgorithms[ea].Ciphers[i - 2]; } + int EAGetNextCipher (int ea, int previousCipherId) { int c, i = 0; @@ -379,6 +476,7 @@ int EAGetNextCipher (int ea, int previou return 0; } + int EAGetPreviousCipher (int ea, int previousCipherId) { int c, i = 0; @@ -395,24 +493,48 @@ int EAGetPreviousCipher (int ea, int pre return 0; } -char *get_hash_algo_name (int hash_algo_id) + +int EAIsFormatEnabled (int ea) { - switch (hash_algo_id) - { - case SHA1: return "SHA-1"; - case RIPEMD160: return "RIPEMD-160"; - case WHIRLPOOL: return "Whirlpool"; - default: return "Unknown"; - } + return EncryptionAlgorithms[ea].FormatEnabled; +} + + +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; } -#ifndef LINUX_DRIVER PCRYPTO_INFO crypto_open () { /* 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)); @@ -448,11 +570,52 @@ crypto_close (PCRYPTO_INFO cryptoInfo) TCfree (cryptoInfo); } } - -#endif // LINUX_DRIVER -// Initializes IV and whitening values for sector encryption/decryption +// Detect weak and potentially weak secondary LRW keys. +// Remark: These tests reduce the key search space by approximately 0.001% +BOOL DetectWeakSecondaryKey (unsigned char *key, int len) +{ +#define LRW_MAX_SUCCESSIVE_IDENTICAL_BITS 24 +#define LRW_MIN_HAMMING_WEIGHT_16 39 +#define LRW_MIN_HAMMING_WEIGHT_8 15 + + int minWeight = (len == 16 ? LRW_MIN_HAMMING_WEIGHT_16 : LRW_MIN_HAMMING_WEIGHT_8); + int i, b, zero = 0, one = 0, zeroTotal = 0, oneTotal = 0; + + for (i = 0; i < len; i++) + { + for (b = 7; b >= 0; b--) + { + if ((key[i] & (1 << b)) == 0) + { + zeroTotal++; + zero++; + one = 0; + } + else + { + oneTotal++; + one++; + zero = 0; + } + + // Maximum number of consecutive identical bit values + if (one >= LRW_MAX_SUCCESSIVE_IDENTICAL_BITS || zero >= LRW_MAX_SUCCESSIVE_IDENTICAL_BITS) + return TRUE; + } + } + + // Minimum and maximum Hamming weight + if (zeroTotal < minWeight || oneTotal < minWeight) + return TRUE; + + return FALSE; +} + + +// 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, int blockSize, @@ -460,6 +623,9 @@ InitSectorIVAndWhitening (unsigned __int unsigned __int64 *ivSeed, unsigned __int32 *whitening) { + + /* IMPORTANT: This function has been deprecated (legacy) */ + unsigned __int64 iv64[4]; unsigned __int32 *iv32 = (unsigned __int32 *) iv64; @@ -498,7 +664,7 @@ InitSectorIVAndWhitening (unsigned __int } -// 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,12 +677,14 @@ 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); @@ -581,7 +749,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,12 +762,15 @@ 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]; @@ -669,60 +840,274 @@ DecryptBufferCBC (unsigned __int32 *data } +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 *plainText, unsigned int length, unsigned __int64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + int cipher = EAGetFirstCipher (cryptoInfo->ea); + int cipherCount = EAGetCipherCount (cryptoInfo->ea); + unsigned __int8 *p = plainText; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[16]; + unsigned int b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + // 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 ); + } + + memset (t, 0, sizeof (t)); +} + + +void EncryptBufferLRW64 (unsigned __int8 *plainText, unsigned int length, unsigned __int64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + int cipher = EAGetFirstCipher (cryptoInfo->ea); + unsigned __int8 *p = plainText; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[8]; + unsigned int b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + 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 ); + } + + memset (t, 0, sizeof (t)); +} + + +void DecryptBufferLRW128 (unsigned __int8 *plainText, int length, unsigned __int64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + int cipher = EAGetFirstCipher (cryptoInfo->ea); + int cipherCount = EAGetCipherCount (cryptoInfo->ea); + unsigned __int8 *p = plainText; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[16]; + int b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + // 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 ); + } + + memset (t, 0, sizeof (t)); +} + + + +void DecryptBufferLRW64 (unsigned __int8 *plainText, int length, unsigned __int64 blockIndex, PCRYPTO_INFO cryptoInfo) +{ + int cipher = EAGetFirstCipher (cryptoInfo->ea); + unsigned __int8 *p = plainText; + unsigned __int8 *ks = cryptoInfo->ks; + unsigned __int8 i[8]; + unsigned __int8 t[8]; + int b; + + *(unsigned __int64 *)i = BE64(blockIndex); + + 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 ); + } + + memset (t, 0, sizeof (t)); +} + + // EncryptBuffer // // 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) + PCRYPTO_INFO cryptoInfo) { - int cipher; - switch (EAGetMode(ea)) + switch (cryptoInfo->mode) { + case LRW: + switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) + { + case 8: + EncryptBufferLRW64 ((unsigned __int8 *)buf, (unsigned int) len, 1, cryptoInfo); + break; + + case 16: + EncryptBufferLRW128 ((unsigned __int8 *)buf, (unsigned int) len, 1, cryptoInfo); + break; + } + break; + case CBC: case INNER_CBC: - - for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) { - EncryptBufferCBC (buf, - (unsigned int) len, - ks, - (unsigned __int32 *) iv, - (unsigned __int32 *) whitening, - 0, - cipher); + /* Deprecated/legacy */ - ks += CipherGetKeyScheduleSize (cipher); - } + unsigned __int8 *ks = cryptoInfo->ks; + int cipher; + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncryptBufferCBC (buf, + (unsigned int) len, + ks, + (unsigned __int32 *) cryptoInfo->iv, + (unsigned __int32 *) &cryptoInfo->iv[8], + 0, + cipher); + ks += CipherGetKeyScheduleSize (cipher); + } + } break; case OUTER_CBC: + /* Deprecated/legacy */ + EncryptBufferCBC (buf, (unsigned int) len, - ks, - (unsigned __int32 *) iv, - (unsigned __int32 *) whitening, - ea, + cryptoInfo->ks, + (unsigned __int32 *) cryptoInfo->iv, + (unsigned __int32 *) &cryptoInfo->iv[8], + cryptoInfo->ea, 0); break; } } +// Convert sector number to the index of the first LRW block in the sector. +// Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). +unsigned __int64 LRWSector2Index (unsigned __int64 sector, int blockSize, PCRYPTO_INFO ci) +{ + if (ci->hiddenVolume) + sector -= ci->hiddenVolumeOffset / SECTOR_SIZE; + else + sector -= HEADER_SIZE / SECTOR_SIZE; // Compensate for the volume header size + + switch (blockSize) + { + case 8: + return (sector << 6) | 1; + + case 16: + return (sector << 5) | 1; + } + + return 0; +} + + // EncryptSectors // // buf: data to be encrypted @@ -732,24 +1117,48 @@ EncryptBuffer (unsigned __int32 *buf, // iv: IV // ea: encryption algorithm -void _cdecl +void 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]; + PCRYPTO_INFO ci) +{ + int ea = ci->ea; + void *iv = ci->iv; // Deprecated/legacy + unsigned __int8 *ks = ci->ks; + unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy + unsigned __int32 sectorIV[4]; // Deprecated/legacy + unsigned __int32 secWhitening[2]; // Deprecated/legacy int cipher; - switch (EAGetMode(ea)) + switch (ci->mode) { + case LRW: + { + switch (CipherGetBlockSize (EAGetFirstCipher (ea))) + { + case 8: + EncryptBufferLRW64 ((unsigned __int8 *)buf, + (unsigned int) noSectors * SECTOR_SIZE, + LRWSector2Index (secNo, 8, ci), + ci); + break; + + case 16: + EncryptBufferLRW128 ((unsigned __int8 *)buf, + (unsigned int) noSectors * SECTOR_SIZE, + LRWSector2Index (secNo, 16, ci), + ci); + break; + } + } + break; + case CBC: case INNER_CBC: + /* Deprecated/legacy */ + while (noSectors--) { for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) @@ -774,6 +1183,8 @@ EncryptSectors (unsigned __int32 *buf, case OUTER_CBC: + /* Deprecated/legacy */ + while (noSectors--) { InitSectorIVAndWhitening (secNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); @@ -798,48 +1209,61 @@ 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) + PCRYPTO_INFO cryptoInfo) { - int cipher; - - switch (EAGetMode(ea)) + switch (cryptoInfo->mode) { + case LRW: + switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) + { + case 8: + DecryptBufferLRW64 ((unsigned __int8 *)buf, (unsigned int) len, 1, cryptoInfo); + break; + + case 16: + DecryptBufferLRW128 ((unsigned __int8 *)buf, (unsigned int) len, 1, cryptoInfo); + break; + } + break; + case CBC: case INNER_CBC: - - ks += EAGetKeyScheduleSize (ea); - for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) { - ks -= CipherGetKeyScheduleSize (cipher); - DecryptBufferCBC (buf, - (unsigned int) len, - ks, - (unsigned __int32 *) iv, - (unsigned __int32 *) whitening, - 0, - cipher); + /* Deprecated/legacy */ + + 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 (buf, + (unsigned int) len, + ks, + (unsigned __int32 *) cryptoInfo->iv, + (unsigned __int32 *) &cryptoInfo->iv[8], + 0, + cipher); + } } break; case OUTER_CBC: + /* Deprecated/legacy */ + DecryptBufferCBC (buf, (unsigned int) len, - ks, - (unsigned __int32 *) iv, - (unsigned __int32 *) whitening, - ea, + cryptoInfo->ks, + (unsigned __int32 *) cryptoInfo->iv, + (unsigned __int32 *) &cryptoInfo->iv[8], + cryptoInfo->ea, 0); break; @@ -855,24 +1279,49 @@ DecryptBuffer (unsigned __int32 *buf, // iv: IV // ea: encryption algorithm -void _cdecl +void 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]; + PCRYPTO_INFO ci +) +{ + int ea = ci->ea; + void *iv = ci->iv; // Deprecated/legacy + unsigned __int8 *ks = ci->ks; + unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy + unsigned __int32 sectorIV[4]; // Deprecated/legacy + unsigned __int32 secWhitening[2]; // Deprecated/legacy int cipher; - switch (EAGetMode(ea)) + switch (ci->mode) { + case LRW: + { + switch (CipherGetBlockSize (EAGetFirstCipher (ea))) + { + case 8: + DecryptBufferLRW64 ((unsigned __int8 *)buf, + (unsigned int) noSectors * SECTOR_SIZE, + LRWSector2Index (secNo, 8, ci), + ci); + break; + + case 16: + DecryptBufferLRW128 ((unsigned __int8 *)buf, + (unsigned int) noSectors * SECTOR_SIZE, + LRWSector2Index (secNo, 16, ci), + ci); + break; + } + } + break; + case CBC: case INNER_CBC: + /* Deprecated/legacy */ + while (noSectors--) { ks += EAGetKeyScheduleSize (ea); @@ -897,6 +1346,8 @@ DecryptSectors (unsigned __int32 *buf, case OUTER_CBC: + /* Deprecated/legacy */ + while (noSectors--) { InitSectorIVAndWhitening (secNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening);