📄 cli.c
字号:
}
else
{
if (fseek (f, 0, SEEK_SET) == -1)
{
perror ("Cannot seek to volume header location");
goto err;
}
}
if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
{
perror ("Cannot write volume header");
goto err;
}
InitProgressBar (totalSectors - 1);
StartSector = startSector;
if (Quick && !hiddenVolume && IsFile (hostPath))
Quick = FALSE;
if (strcasecmp ("FAT", Filesystem) == 0)
{
if (hiddenVolume)
{
if (fseeko (f, startSector * SECTOR_SIZE, SEEK_SET) == -1)
{
perror ("Cannot seek to hidden volume data area");
goto err;
}
}
ft.num_sectors = (unsigned int) totalSectors - 1;
ft.cluster_size = ClusterSize;
memcpy (ft.volume_name, "NO NAME ", 11);
GetFatParams (&ft);
r = FormatFat (startSector, &ft, f, ci, Quick);
}
else if (!hiddenVolume)
{
r = FormatNoFs (startSector, totalSectors - 1, f, ci, Quick);
}
if (r == ERR_OS_ERROR)
{
perror ("Volume creation failed");
goto err;
}
if (DisplayProgress && IsTerminal)
puts ("\nVolume created.");
ret = TRUE;
err:
if (ci)
crypto_close (ci);
if (f)
fclose (f);
if (!ret && deleteOnError && IsFile (hostPath))
remove (hostPath);
Randfree ();
return ret;
}
static BOOL ChangePassword (char *volumePath)
{
char header[HEADER_SIZE];
char path[TC_MAX_PATH];
Password *pw = &password;
PCRYPTO_INFO ci = NULL, ci2 = NULL;
unsigned long long startSector, totalSectors;
time_t modTime = 0, acTime;
int wipePass, ret = FALSE;
int fd = -1, r;
FILE *f;
// Volume path
volumePath = AskVolumePath (volumePath, "Enter volume path");
if (!NoKeyFiles && !FirstKeyFile)
AskKeyFiles ("Enter current keyfile path", &FirstKeyFile);
// Open volume
if (!OpenVolume (volumePath, "Enter current password for '%s': ", volumePath, FALSE,
&ci, &startSector, &totalSectors, &modTime, &acTime))
return FALSE;
puts ("");
// New password and/or keyfile(s)
if (!NoNewKeyFiles && !FirstNewKeyFile)
AskKeyFiles ("Enter new keyfile path", &FirstNewKeyFile);
if (!CmdPassword2Valid)
{
while (1)
{
AskPassword ("Enter new password for '%s': ", volumePath, &password);
if (!DisplayPassword)
{
Password pv;
AskPassword ("Re-enter new password%s", ": ", &pv);
if (password.Length != pv.Length || memcmp (password.Text, pv.Text, pv.Length))
{
puts ("Passwords do not match.\n");
continue;
}
}
break;
}
puts ("");
}
else
pw = &CmdPassword2;
if (!FirstNewKeyFile && pw->Length == 0)
{
error ("Password cannot be empty when no keyfiles are specified\n");
goto err;
}
if (FirstNewKeyFile && !KeyFilesApply (pw, FirstNewKeyFile, !UpdateTime))
{
error ("Error while processing new keyfiles\n");
goto err;
}
fd = open (volumePath, O_RDWR | O_SYNC);
if (fd == -1)
{
perror ("Cannot open file or device");
goto err;
}
OpenMiceDevice ();
if (!RandFillPool ())
goto err;
f = fdopen (fd, "r+b");
// Write a new volume header
for (wipePass = 0; wipePass < DISK_WIPE_PASSES; wipePass++)
{
BOOL wipeMode = wipePass < DISK_WIPE_PASSES - 1;
if (Verbose)
{
printf ("\rWriting header (pass %d)%s", wipePass, wipeMode ? "" : "\n");
fflush (stdout);
}
r = VolumeWriteHeader (header,
ci->ea,
ci->mode,
pw,
HashAlgorithm == 0 ? ci->pkcs5 : HashAlgorithm,
(char *)ci->master_key,
ci->volume_creation_time,
&ci2,
ci->hiddenVolumeSize,
wipeMode);
if (r == ERR_CIPHER_INIT_WEAK_KEY)
{
error ("A weak or a potentially weak key has been generated. Please try again.\n");
goto err;
}
if (r != 0)
{
error ("Volume header creation failed.\n");
goto err;
}
crypto_close (ci2);
ci2 = NULL;
if (ci->hiddenVolumeSize)
{
if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1)
{
perror ("Cannot seek to hidden volume header location");
goto err;
}
}
else
{
if (fseek (f, 0, SEEK_SET) == -1)
{
perror ("Cannot seek to volume header location");
goto err;
}
}
if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
{
perror ("Cannot write volume header");
goto err;
}
fflush (f);
fdatasync (fd);
}
if (Verbose)
puts ("");
printf ("Password %schanged.\n", FirstKeyFile && FirstNewKeyFile ? "and/or keyfile(s) " : "");
if (!FirstKeyFile && FirstNewKeyFile)
puts ("Keyfiles added.");
if (FirstKeyFile && !FirstNewKeyFile)
puts ("Keyfiles removed.");
ret = TRUE;
err:
if (ci)
crypto_close (ci);
if (fd != -1)
close (fd);
if (!UpdateTime && modTime != 0)
RestoreFileTime (volumePath, modTime, acTime);
Randfree ();
return ret;
}
static BOOL BackupVolumeHeaders (char *backupFile, char *volumePath)
{
char path[TC_MAX_PATH];
char header[HEADER_SIZE * 2];
FILE *f = NULL, *fb = NULL;
struct stat volumeStat;
int ret = FALSE;
DropEffectiveUserId ();
// Volume path
volumePath = AskVolumePath (volumePath, "Enter volume path");
if (strcmp (backupFile, volumePath) == 0)
{
error ("Volume path identical to backup file\n");
goto err;
}
volumeStat.st_mtime = 0;
if (IsFile (volumePath) && stat (volumePath, &volumeStat) != 0)
{
perror ("Cannot read volume's modification and access time");
volumeStat.st_mtime = 0;
goto err;
}
// Volume
f = fopen (volumePath, "rb");
if (!f)
{
perror ("Cannot open volume");
goto err;
}
if (fread (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
{
perror ("Cannot read volume header");
goto err;
}
if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1)
{
perror ("Cannot seek to hidden volume header location");
goto err;
}
if (fread (header + HEADER_SIZE, 1, HEADER_SIZE, f) != HEADER_SIZE)
{
perror ("Cannot read hidden volume header");
goto err;
}
// Backup file
fb = fopen (backupFile, "wb");
if (!fb)
{
perror ("Cannot open backup file");
goto err;
}
if (fwrite (header, 1, HEADER_SIZE * 2, fb) != HEADER_SIZE * 2)
{
perror ("Cannot write backup file");
goto err;
}
ret = TRUE;
err:
if (f)
fclose (f);
if (f)
fclose (fb);
if (!UpdateTime && volumeStat.st_mtime != 0)
RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
return ret;
}
static BOOL RestoreVolumeHeader (char *backupFile, char *volumePath)
{
char path[TC_MAX_PATH];
char header[HEADER_SIZE];
FILE *f = NULL, *fb = NULL;
struct stat volumeStat;
int ret = FALSE;
BOOL hiddenVolume;
DropEffectiveUserId ();
// Backup file
fb = fopen (backupFile, "rb");
if (!fb)
{
perror ("Cannot open backup file");
goto err;
}
// Volume path
volumePath = AskVolumePath (volumePath, "Enter volume path");
if (strcmp (backupFile, volumePath) == 0)
{
error ("Volume path identical to backup file\n");
goto err;
}
// Volume type
switch (VolumeType)
{
case VOLUME_TYPE_NORMAL:
hiddenVolume = FALSE;
break;
case VOLUME_TYPE_HIDDEN:
hiddenVolume = TRUE;
Quick = TRUE;
break;
default:
puts ("Restore header of:\n 1) Normal/Outer Volume\n 2) Hidden Volume");
hiddenVolume = AskSelection (1, 1, 2) == 2;
break;
}
volumeStat.st_mtime = 0;
if (IsFile (volumePath) && stat (volumePath, &volumeStat) != 0)
{
perror ("Cannot read volume's modification and access time");
volumeStat.st_mtime = 0;
goto err;
}
f = fopen (volumePath, "r+b");
if (!f)
{
perror ("Cannot open volume");
goto err;
}
if (hiddenVolume)
{
if (fseek (fb, HEADER_SIZE, SEEK_SET) == -1)
{
perror ("Cannot seek to hidden volume header location in backup file");
goto err;
}
if (fseek (f, -HIDDEN_VOL_HEADER_OFFSET, SEEK_END) == -1)
{
perror ("Cannot seek to hidden volume header location");
goto err;
}
}
if (fread (header, 1, HEADER_SIZE, fb) != HEADER_SIZE)
{
perror ("Cannot read backup file");
goto err;
}
if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
{
perror ("Cannot write volume header");
goto err;
}
ret = TRUE;
err:
if (f)
fclose (f);
if (f)
fclose (fb);
if (!UpdateTime && volumeStat.st_mtime != 0)
RestoreFileTime (volumePath, volumeStat.st_mtime, volumeStat.st_atime);
return ret;
}
static BOOL CreateKeyfile (char *path)
{
uint8_t keyFile[MAX_PASSWORD];
FILE *f = NULL;
int ret = FALSE;
OpenMiceDevice ();
DropEffectiveUserId ();
if (!Overwrite
&& IsFile (path)
&& (!IsTerminal || !AskYesNo ("Keyfile already exists - overwrite?", TRUE)))
{
if (!IsTerminal)
error ("Keyfile already exists.\n");
return FALSE;
}
f = fopen (path, "wb");
if (!f)
{
perror ("Cannot open file");
goto err;
}
if (!RandFillPool ())
goto err;
if (!RandgetBytes (keyFile, sizeof (keyFile), FALSE))
goto err;
if (fwrite (keyFile, 1, sizeof (keyFile), f) != sizeof (keyFile))
{
perror ("Cannot write file");
goto err;
}
puts ("Keyfile created.");
ret = TRUE;
err:
if (f)
fclose (f);
Randfree ();
return ret;
}
static time_t WindowsFileTime2UnixTime (uint64_t wTime)
{
return (time_t) (wTime / 1000LL / 1000 / 10 - 134774LL * 24 * 3600);
}
static BOOL DumpVolumeProperties (char *volumePath)
{
unsigned long long startSector, totalSectors;
time_t modTime = 0, acTime;
PCRYPTO_INFO ci = NULL;
BOOL ret = FALSE;
char eaName[256], timeBuf[256], timeBuf2[256];
int keySize;
time_t volCTime, headerMTime;
volumePath = AskVolumePath (volumePath, "Enter volume path");
if (!NoKeyFiles && !FirstKeyFile)
AskKeyFiles ("Enter keyfile path", &FirstKeyFile);
if (!OpenVolume (volumePath, "Enter password for '%s': ", volumePath, FALSE,
&ci, &startSector, &totalSectors, &modTime, &acTime))
goto err;
EAGetName (eaName, ci->ea);
keySize = EAGetKeySize (ci->ea);
if (strcmp (eaName, "Triple DES") == 0)
keySize -= 3; // Compensate for parity bytes
volCTime = WindowsFileTime2UnixTime (ci->volume_creation_time);
headerMTime = WindowsFileTime2UnixTime (ci->header_creation_time);
printf ("%sVolume properties:\n"
" Location: %s\n"
" Size: %llu bytes\n"
" Type: %s\n"
" Encryption algorithm: %s\n"
" Key size: %d bits\n"
" Block size: %d bits\n"
" Mode of operation: %s\n"
" PKCS-5 PRF: %s\n"
" PKCS-5 iteration count: %d\n"
,
CmdPasswordValid ? "" : "\n",
volumePath,
totalSectors * SECTOR_SIZE,
ci->hiddenVolumeSize == 0 ? "Normal" : "Hidden",
eaName,
keySize * 8,
CipherGetBlockSize (EAGetFirstCipher(ci->ea)) * 8,
EAGetModeName (ci->ea, ci->mode, TRUE),
get_pkcs5_prf_name (ci->pkcs5),
ci->noIterations
);
// Separated from above to prevent seg faults in buggy libraries
printf (" Volume created: %s"
" Header modified: %s",
ctime_r (&volCTime, timeBuf),
ctime_r (&headerMTime, timeBuf2));
ret = TRUE;
err:
if (ci != NULL)
crypto_close (ci);
if (!UpdateTime && modTime != 0)
RestoreFileTime (volumePath, modTime, acTime);
return ret;
}
static void DumpVersion (FILE *f)
{
fprintf (f,
"truecrypt %s\n\n\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -