📄 keyfiles.c
字号:
/*
Copyright (c) 2005 TrueCrypt Foundation. All rights reserved.
Governed by the TrueCrypt License 2.6 the full text of which is contained
in the file License.txt included in TrueCrypt binary and source code
distribution packages.
*/
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "Tcdefs.h"
#include "Keyfiles.h"
#include "Crc.h"
#include <io.h>
#include "Dlgcode.h"
#include "Language.h"
#include "SecurityToken.h"
#include "Common/resource.h"
#include "Platform/ForEach.h"
using namespace TrueCrypt;
#define stat _stat
#define S_IFDIR _S_IFDIR
#define snprintf _snprintf
KeyFile *KeyFileAdd (KeyFile *firstKeyFile, KeyFile *keyFile)
{
KeyFile *kf = firstKeyFile;
if (firstKeyFile != NULL)
{
while (kf->Next)
kf = kf->Next;
kf->Next = keyFile;
}
else
firstKeyFile = keyFile;
keyFile->Next = NULL;
return firstKeyFile;
}
// Returns first keyfile, NULL if last keyfile was removed
static KeyFile *KeyFileRemove (KeyFile *firstKeyFile, KeyFile *keyFile)
{
KeyFile *prevkf = NULL, *kf = firstKeyFile;
if (firstKeyFile == NULL) return NULL;
do
{
if (kf == keyFile)
{
if (prevkf == NULL)
firstKeyFile = kf->Next;
else
prevkf->Next = kf->Next;
burn (keyFile, sizeof(*keyFile)); // wipe
free (keyFile);
break;
}
prevkf = kf;
}
while (kf = kf->Next);
return firstKeyFile;
}
void KeyFileRemoveAll (KeyFile **firstKeyFile)
{
KeyFile *kf = *firstKeyFile;
while (kf != NULL)
{
KeyFile *d = kf;
kf = kf->Next;
burn (d, sizeof(*d)); // wipe
free (d);
}
*firstKeyFile = NULL;
}
KeyFile *KeyFileClone (KeyFile *keyFile)
{
KeyFile *clone;
if (keyFile == NULL) return NULL;
clone = (KeyFile *) malloc (sizeof (KeyFile));
strcpy (clone->FileName, keyFile->FileName);
clone->Next = NULL;
return clone;
}
KeyFile *KeyFileCloneAll (KeyFile *firstKeyFile)
{
KeyFile *cloneFirstKeyFile = KeyFileClone (firstKeyFile);
KeyFile *kf;
if (firstKeyFile == NULL) return NULL;
kf = firstKeyFile->Next;
while (kf != NULL)
{
KeyFileAdd (cloneFirstKeyFile, KeyFileClone (kf));
kf = kf->Next;
}
return cloneFirstKeyFile;
}
static BOOL KeyFileProcess (unsigned __int8 *keyPool, KeyFile *keyFile)
{
FILE *f;
unsigned __int8 buffer[64 * 1024];
unsigned __int32 crc = 0xffffffff;
int writePos = 0;
size_t bytesRead, totalRead = 0;
int status = TRUE;
HANDLE src;
FILETIME ftCreationTime;
FILETIME ftLastWriteTime;
FILETIME ftLastAccessTime;
BOOL bTimeStampValid = FALSE;
/* Remember the last access time of the keyfile. It will be preserved in order to prevent
an adversary from determining which file may have been used as keyfile. */
src = CreateFile (keyFile->FileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (src != INVALID_HANDLE_VALUE)
{
if (GetFileTime ((HANDLE) src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
bTimeStampValid = TRUE;
else
Warning ("GETFILETIME_FAILED_KEYFILE");
}
f = fopen (keyFile->FileName, "rb");
if (f == NULL) return FALSE;
while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0)
{
size_t i;
if (ferror (f))
{
status = FALSE;
goto close;
}
for (i = 0; i < bytesRead; i++)
{
crc = UPDC32 (buffer[i], crc);
keyPool[writePos++] += (unsigned __int8) (crc >> 24);
keyPool[writePos++] += (unsigned __int8) (crc >> 16);
keyPool[writePos++] += (unsigned __int8) (crc >> 8);
keyPool[writePos++] += (unsigned __int8) crc;
if (writePos >= KEYFILE_POOL_SIZE)
writePos = 0;
if (++totalRead >= KEYFILE_MAX_READ_LEN)
goto close;
}
}
if (ferror (f))
{
status = FALSE;
}
else if (totalRead == 0)
{
status = FALSE;
SetLastError (ERROR_HANDLE_EOF);
}
close:
DWORD err = GetLastError();
fclose (f);
if (bTimeStampValid && !IsFileOnReadOnlyFilesystem (keyFile->FileName))
{
// Restore the keyfile timestamp
if (!SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
Warning ("SETFILETIME_FAILED_KEYFILE");
CloseHandle (src);
}
SetLastError (err);
return status;
}
BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile)
{
BOOL status = TRUE;
KeyFile kfSubStruct;
KeyFile *kf;
KeyFile *kfSub = &kfSubStruct;
static unsigned __int8 keyPool [KEYFILE_POOL_SIZE];
size_t i;
struct stat statStruct;
char searchPath [TC_MAX_PATH*2];
struct _finddata_t fBuf;
intptr_t searchHandle;
if (firstKeyFile == NULL) return TRUE;
VirtualLock (keyPool, sizeof (keyPool));
memset (keyPool, 0, sizeof (keyPool));
for (kf = firstKeyFile; kf != NULL; kf = kf->Next)
{
// Determine whether it's a security token path
try
{
if (SecurityToken::IsKeyfilePathValid (SingleStringToWide (kf->FileName)))
{
// Apply security token keyfile
vector <byte> keyfileData;
SecurityToken::GetKeyfileData (SecurityTokenKeyfile (SingleStringToWide (kf->FileName)), keyfileData);
if (keyfileData.empty())
{
SetLastError (ERROR_HANDLE_EOF);
handleWin32Error (MainDlg);
Error ("ERR_PROCESS_KEYFILE");
status = FALSE;
continue;
}
unsigned __int32 crc = 0xffffffff;
int writePos = 0;
size_t totalRead = 0;
for (size_t i = 0; i < keyfileData.size(); i++)
{
crc = UPDC32 (keyfileData[i], crc);
keyPool[writePos++] += (unsigned __int8) (crc >> 24);
keyPool[writePos++] += (unsigned __int8) (crc >> 16);
keyPool[writePos++] += (unsigned __int8) (crc >> 8);
keyPool[writePos++] += (unsigned __int8) crc;
if (writePos >= KEYFILE_POOL_SIZE)
writePos = 0;
if (++totalRead >= KEYFILE_MAX_READ_LEN)
break;
}
burn (&keyfileData.front(), keyfileData.size());
continue;
}
}
catch (Exception &e)
{
e.Show (NULL);
return FALSE;
}
// Determine whether it's a path or a file
if (stat (kf->FileName, &statStruct) != 0)
{
handleWin32Error (MainDlg);
Error ("ERR_PROCESS_KEYFILE");
status = FALSE;
continue;
}
if (statStruct.st_mode & S_IFDIR) // If it's a directory
{
/* Find and process all keyfiles in the directory */
snprintf (searchPath, sizeof (searchPath), "%s\\*.*", kf->FileName);
if ((searchHandle = _findfirst (searchPath, &fBuf)) == -1)
{
handleWin32Error (MainDlg);
Error ("ERR_PROCESS_KEYFILE_PATH");
status = FALSE;
continue;
}
do
{
snprintf (kfSub->FileName, sizeof(kfSub->FileName), "%s%c%s", kf->FileName,
'\\',
fBuf.name
);
// Determine whether it's a path or a file
if (stat (kfSub->FileName, &statStruct) != 0)
{
handleWin32Error (MainDlg);
Error ("ERR_PROCESS_KEYFILE");
status = FALSE;
continue;
}
else if (statStruct.st_mode & S_IFDIR) // If it's a directory
{
// Prevent recursive folder scanning
continue;
}
// Apply keyfile to the pool
if (!KeyFileProcess (keyPool, kfSub))
{
handleWin32Error (MainDlg);
Error ("ERR_PROCESS_KEYFILE");
status = FALSE;
}
} while (_findnext (searchHandle, &fBuf) != -1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -