📄 crypto.c
字号:
for (mode = EAGetFirstMode (ea); mode != 0; mode = EAGetNextMode (ea, mode))
{
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;
}
#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 = (PCRYPTO_INFO) TCalloc (sizeof (CRYPTO_INFO));
memset (cryptoInfo, 0, sizeof (CRYPTO_INFO));
#ifndef DEVICE_DRIVER
VirtualLock (cryptoInfo, sizeof (CRYPTO_INFO));
#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)
{
keyInfo->keyLength = nUserKeyLen;
burn (keyInfo->userKey, sizeof (keyInfo->userKey));
memcpy (keyInfo->userKey, lpszUserKey, nUserKeyLen);
}
void crypto_close (PCRYPTO_INFO cryptoInfo)
{
#ifndef TC_WINDOWS_BOOT
if (cryptoInfo != NULL)
{
burn (cryptoInfo, sizeof (CRYPTO_INFO));
#ifndef DEVICE_DRIVER
VirtualUnlock (cryptoInfo, sizeof (CRYPTO_INFO));
#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));
}
// Initializes IV and whitening values for sector encryption/decryption in CBC mode.
// IMPORTANT: This function has been deprecated (legacy).
static void
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(unitNo);
iv64[1] = ivSeed[1] ^ LE64(unitNo);
iv64[2] = ivSeed[2] ^ LE64(unitNo);
if (blockSize == 16)
{
iv64[3] = ivSeed[3] ^ LE64(unitNo);
}
iv[0] = iv32[0];
iv[1] = iv32[1];
switch (blockSize)
{
case 16:
// 128-bit block
iv[2] = iv32[2];
iv[3] = iv32[3];
whitening[0] = LE32( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) );
whitening[1] = LE32( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) );
break;
case 8:
// 64-bit block
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 (deprecated/legacy)
//
// data: data to be encrypted
// len: number of bytes to encrypt (must be divisible by the largest cipher block size)
// ks: scheduled key
// iv: IV
// whitening: whitening constants
// ea: outer-CBC cascade ID (0 = CBC/inner-CBC)
// cipher: CBC/inner-CBC cipher ID (0 = outer-CBC)
static void
EncryptBufferCBC (unsigned __int32 *data,
unsigned int len,
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];
if (blockSize == 16)
{
bufIV[2] = iv[2];
bufIV[3] = iv[3];
}
// Encrypt each block
for (i = 0; i < len/blockSize; i++)
{
// CBC
data[0] ^= bufIV[0];
data[1] ^= bufIV[1];
if (blockSize == 16)
{
data[2] ^= bufIV[2];
data[3] ^= bufIV[3];
}
if (ea != 0)
{
// Outer-CBC
for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher))
{
EncipherBlock (cipher, data, ks);
ks += CipherGetKeyScheduleSize (cipher);
}
ks -= EAGetKeyScheduleSize (ea);
}
else
{
// CBC/inner-CBC
EncipherBlock (cipher, data, ks);
}
// CBC
bufIV[0] = data[0];
bufIV[1] = data[1];
if (blockSize == 16)
{
bufIV[2] = data[2];
bufIV[3] = data[3];
}
// Whitening
data[0] ^= whitening[0];
data[1] ^= whitening[1];
if (blockSize == 16)
{
data[2] ^= whitening[0];
data[3] ^= whitening[1];
}
data += blockSize / sizeof(*data);
}
}
// DecryptBufferCBC (deprecated/legacy)
//
// data: data to be decrypted
// len: number of bytes to decrypt (must be divisible by the largest cipher block size)
// ks: scheduled key
// iv: IV
// whitening: whitening constants
// ea: outer-CBC cascade ID (0 = CBC/inner-CBC)
// cipher: CBC/inner-CBC cipher ID (0 = outer-CBC)
static void
DecryptBufferCBC (unsigned __int32 *data,
unsigned int len,
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];
if (blockSize == 16)
{
bufIV[2] = iv[2];
bufIV[3] = iv[3];
}
// Decrypt each block
for (i = 0; i < len/blockSize; i++)
{
// Dewhitening
data[0] ^= whitening[0];
data[1] ^= whitening[1];
if (blockSize == 16)
{
data[2] ^= whitening[0];
data[3] ^= whitening[1];
}
// CBC
ct[0] = data[0];
ct[1] = data[1];
if (blockSize == 16)
{
ct[2] = data[2];
ct[3] = data[3];
}
if (ea != 0)
{
// Outer-CBC
ks += EAGetKeyScheduleSize (ea);
for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher))
{
ks -= CipherGetKeyScheduleSize (cipher);
DecipherBlock (cipher, data, ks);
}
}
else
{
// CBC/inner-CBC
DecipherBlock (cipher, data, ks);
}
// CBC
data[0] ^= bufIV[0];
data[1] ^= bufIV[1];
bufIV[0] = ct[0];
bufIV[1] = ct[1];
if (blockSize == 16)
{
data[2] ^= bufIV[2];
data[3] ^= bufIV[3];
bufIV[2] = ct[2];
bufIV[3] = ct[3];
}
data += blockSize / sizeof(*data);
}
}
#endif // #ifndef TC_NO_COMPILER_INT64
// 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
// by the largest block size used within the cascade)
void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo)
{
switch (cryptoInfo->mode)
{
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 assumed to be aligned with the start of a data unit.
dataUnitNo.LowPart = 0;
dataUnitNo.HighPart = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -