📄 volumes.c
字号:
// Secondary key schedule
EAInit (cryptoInfo->ea, dk + EAGetKeySize (cryptoInfo->ea), cryptoInfo->ks2);
// Try to decrypt header
DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
// Check magic 'TRUE' and key CRC
if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545
|| GetHeaderField32 (header, TC_HEADER_OFFSET_KEY_AREA_CRC) != GetCrc32 (header + HEADER_MASTER_KEYDATA_OFFSET, MASTER_KEYDATA_SIZE))
{
EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
continue;
}
// Header decrypted
status = 0;
// Volume size
cryptoInfo->VolumeSize = GetHeaderField64 (header, TC_HEADER_OFFSET_VOLUME_SIZE);
// Encrypted area size and length
cryptoInfo->EncryptedAreaStart = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_START);
cryptoInfo->EncryptedAreaLength = GetHeaderField64 (header, TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH);
memcpy (masterKey, header + HEADER_MASTER_KEYDATA_OFFSET, sizeof (masterKey));
EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
if (retHeaderCryptoInfo)
goto ret;
// Init the encryption algorithm with the decrypted master key
status = EAInit (cryptoInfo->ea, masterKey, cryptoInfo->ks);
if (status == ERR_CIPHER_INIT_FAILURE)
goto err;
// The secondary master key (if cascade, multiple concatenated)
EAInit (cryptoInfo->ea, masterKey + EAGetKeySize (cryptoInfo->ea), cryptoInfo->ks2);
goto ret;
}
status = ERR_PASSWORD_WRONG;
err:
if (cryptoInfo != retHeaderCryptoInfo)
{
crypto_close(cryptoInfo);
*retInfo = NULL;
}
ret:
burn (dk, sizeof(dk));
burn (masterKey, sizeof(masterKey));
return status;
}
#endif // TC_WINDOWS_BOOT
#if !defined (DEVICE_DRIVER) && !defined (TC_WINDOWS_BOOT)
#ifdef VOLFORMAT
#include "../Format/TcFormat.h"
#endif
// Creates a volume header in memory
int VolumeWriteHeader (BOOL bBoot, char *header, int ea, int mode, Password *password,
int pkcs5_prf, char *masterKeydata, unsigned __int64 volumeCreationTime, PCRYPTO_INFO *retInfo,
unsigned __int64 volumeSize, unsigned __int64 hiddenVolumeSize,
unsigned __int64 encryptedAreaStart, unsigned __int64 encryptedAreaLength, BOOL bWipeMode)
{
unsigned char *p = (unsigned char *) header;
static KEY_INFO keyInfo;
int nUserKeyLen = password->Length;
PCRYPTO_INFO cryptoInfo = crypto_open ();
static char dk[MASTER_KEYDATA_SIZE];
int x;
int retVal = 0;
int primaryKeyOffset;
if (cryptoInfo == NULL)
return ERR_OUTOFMEMORY;
memset (header, 0, HEADER_SIZE);
#ifdef _WIN32
VirtualLock (&keyInfo, sizeof (keyInfo));
VirtualLock (&dk, sizeof (dk));
#endif
/* Encryption setup */
if (masterKeydata == NULL)
{
// We have no master key data (creating a new volume) so we'll use the TrueCrypt RNG to generate them
int bytesNeeded;
switch (mode)
{
case LRW:
case CBC:
case INNER_CBC:
case OUTER_CBC:
// Deprecated/legacy modes of operation
bytesNeeded = LEGACY_VOL_IV_SIZE + EAGetKeySize (ea);
/* In fact, this should never be the case since new volumes are not supposed to use
any deprecated mode of operation. */
return ERR_VOL_FORMAT_BAD;
default:
bytesNeeded = EAGetKeySize (ea) * 2; // Size of primary + secondary key(s)
}
if (!RandgetBytes (keyInfo.master_keydata, bytesNeeded, TRUE))
return ERR_CIPHER_INIT_WEAK_KEY;
}
else
{
// We already have existing master key data (the header is being re-encrypted)
memcpy (keyInfo.master_keydata, masterKeydata, MASTER_KEYDATA_SIZE);
}
// User key
memcpy (keyInfo.userKey, password->Text, nUserKeyLen);
keyInfo.keyLength = nUserKeyLen;
keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, bBoot);
// User selected encryption algorithm
cryptoInfo->ea = ea;
// Mode of operation
cryptoInfo->mode = mode;
// Salt for header key derivation
if (!RandgetBytes (keyInfo.salt, PKCS5_SALT_SIZE, !bWipeMode))
return ERR_CIPHER_INIT_WEAK_KEY;
// PBKDF2 (PKCS5) is used to derive primary header key(s) and secondary header key(s) (XTS) from the password/keyfiles
switch (pkcs5_prf)
{
case SHA512:
derive_key_sha512 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
case SHA1:
// Deprecated/legacy
derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
case RIPEMD160:
derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
case WHIRLPOOL:
derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
}
/* Header setup */
// Salt
mputBytes (p, keyInfo.salt, PKCS5_SALT_SIZE);
// Magic
mputLong (p, 0x54525545);
// Header version
switch (mode)
{
case LRW:
case CBC:
case OUTER_CBC:
case INNER_CBC:
// Deprecated/legacy modes (used before TrueCrypt 5.0)
mputWord (p, 0x0002);
break;
default:
mputWord (p, VOLUME_HEADER_VERSION);
}
// Required program version to handle this volume
switch (mode)
{
case LRW:
// Deprecated/legacy
mputWord (p, 0x0410);
break;
case OUTER_CBC:
case INNER_CBC:
// Deprecated/legacy
mputWord (p, 0x0300);
break;
case CBC:
// Deprecated/legacy
mputWord (p, hiddenVolumeSize > 0 ? 0x0300 : 0x0100);
break;
default:
mputWord (p, VOL_REQ_PROG_VERSION);
}
// CRC of the master key data
x = GetCrc32(keyInfo.master_keydata, MASTER_KEYDATA_SIZE);
mputLong (p, x);
// Time
{
#ifdef _WIN32
SYSTEMTIME st;
FILETIME ft;
// Volume creation time
if (volumeCreationTime == 0)
{
GetLocalTime (&st);
SystemTimeToFileTime (&st, &ft);
}
else
{
ft.dwHighDateTime = (DWORD)(volumeCreationTime >> 32);
ft.dwLowDateTime = (DWORD)volumeCreationTime;
}
mputLong (p, ft.dwHighDateTime);
mputLong (p, ft.dwLowDateTime);
// Header modification time/date
GetLocalTime (&st);
SystemTimeToFileTime (&st, &ft);
mputLong (p, ft.dwHighDateTime);
mputLong (p, ft.dwLowDateTime);
#else
struct timeval tv;
unsigned __int64 ct, wt;
gettimeofday (&tv, NULL);
// Unix time => Windows file time
wt = ((unsigned __int64)tv.tv_sec + 134774LL * 24 * 3600) * 1000LL * 1000 * 10;
if (volumeCreationTime == 0)
ct = wt;
else
ct = volumeCreationTime;
mputInt64 (p, ct);
mputInt64 (p, wt);
#endif
}
// Size of hidden volume (if any)
cryptoInfo->hiddenVolumeSize = hiddenVolumeSize;
mputInt64 (p, cryptoInfo->hiddenVolumeSize);
cryptoInfo->hiddenVolume = cryptoInfo->hiddenVolumeSize != 0;
// Volume size
cryptoInfo->VolumeSize.Value = volumeSize;
mputInt64 (p, volumeSize);
// Encrypted area start
cryptoInfo->EncryptedAreaStart.Value = encryptedAreaStart;
mputInt64 (p, encryptedAreaStart);
// Encrypted area size
cryptoInfo->EncryptedAreaLength.Value = encryptedAreaLength;
mputInt64 (p, encryptedAreaLength);
// The master key data
memcpy (header + HEADER_MASTER_KEYDATA_OFFSET, keyInfo.master_keydata, MASTER_KEYDATA_SIZE);
/* Header encryption */
switch (mode)
{
case LRW:
case CBC:
case INNER_CBC:
case OUTER_CBC:
// For LRW (deprecated/legacy), the tweak key
// For CBC (deprecated/legacy), the IV/whitening seed
memcpy (cryptoInfo->k2, dk, LEGACY_VOL_IV_SIZE);
primaryKeyOffset = LEGACY_VOL_IV_SIZE;
break;
default:
// The secondary key (if cascade, multiple concatenated)
memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea));
primaryKeyOffset = 0;
}
retVal = EAInit (cryptoInfo->ea, dk + primaryKeyOffset, cryptoInfo->ks);
if (retVal != ERR_SUCCESS)
return retVal;
// Mode of operation
if (!EAInitMode (cryptoInfo))
return ERR_OUTOFMEMORY;
// Encrypt the entire header (except the salt)
EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET,
HEADER_ENCRYPTED_DATA_SIZE,
cryptoInfo);
/* cryptoInfo setup for further use (disk format) */
// Init with the master key(s)
retVal = EAInit (cryptoInfo->ea, keyInfo.master_keydata + primaryKeyOffset, cryptoInfo->ks);
if (retVal != ERR_SUCCESS)
return retVal;
memcpy (cryptoInfo->master_keydata, keyInfo.master_keydata, MASTER_KEYDATA_SIZE);
switch (cryptoInfo->mode)
{
case LRW:
case CBC:
case INNER_CBC:
case OUTER_CBC:
// For LRW (deprecated/legacy), the tweak key
// For CBC (deprecated/legacy), the IV/whitening seed
memcpy (cryptoInfo->k2, keyInfo.master_keydata, LEGACY_VOL_IV_SIZE);
break;
default:
// The secondary master key (if cascade, multiple concatenated)
memcpy (cryptoInfo->k2, keyInfo.master_keydata + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea));
}
// Mode of operation
if (!EAInitMode (cryptoInfo))
return ERR_OUTOFMEMORY;
#ifdef VOLFORMAT
if (showKeys)
{
BOOL dots3 = FALSE;
int i, j;
j = EAGetKeySize (ea);
if (j > NBR_KEY_BYTES_TO_DISPLAY)
{
dots3 = TRUE;
j = NBR_KEY_BYTES_TO_DISPLAY;
}
MasterKeyGUIView[0] = 0;
for (i = 0; i < j; i++)
{
char tmp2[8] = {0};
sprintf (tmp2, "%02X", (int) (unsigned char) keyInfo.master_keydata[i + primaryKeyOffset]);
strcat (MasterKeyGUIView, tmp2);
}
if (dots3)
{
strcat (MasterKeyGUIView, "...");
}
SendMessage (hMasterKey, WM_SETTEXT, 0, (LPARAM) MasterKeyGUIView);
HeaderKeyGUIView[0] = 0;
for (i = 0; i < NBR_KEY_BYTES_TO_DISPLAY; i++)
{
char tmp2[8];
sprintf (tmp2, "%02X", (int) (unsigned char) dk[primaryKeyOffset + i]);
strcat (HeaderKeyGUIView, tmp2);
}
if (dots3)
{
strcat (HeaderKeyGUIView, "...");
}
SendMessage (hHeaderKey, WM_SETTEXT, 0, (LPARAM) HeaderKeyGUIView);
}
#endif // #ifdef VOLFORMAT
burn (dk, sizeof(dk));
burn (&keyInfo, sizeof (keyInfo));
*retInfo = cryptoInfo;
return 0;
}
#endif // !defined (DEVICE_DRIVER) && !defined (TC_WINDOWS_BOOT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -