/* Derived from source code of TrueCrypt 7.1a, which is Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0. Modifications and additions to the original source code (contained in this file) and all other portions of this file are Copyright (c) 2013-2015 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ #include #include #include #include #include "Tcdefs.h" #include "Keyfiles.h" #include "Crc.h" #include #include "Dlgcode.h" #include "Language.h" #include "SecurityToken.h" #include "Common/resource.h" #include "Platform/Finally.h" #include "Platform/ForEach.h" #include using namespace VeraCrypt; #define stat _stat #define S_IFDIR _S_IFDIR BOOL HiddenFilesPresentInKeyfilePath = FALSE; 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 = NULL; if (keyFile == NULL) return NULL; clone = (KeyFile *) malloc (sizeof (KeyFile)); if (clone) { StringCbCopyA (clone->FileName, sizeof(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; } finally_do_arg (HANDLE, src, { if (finally_arg != INVALID_HANDLE_VALUE) CloseHandle (finally_arg); }); 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 SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime); } SetLastError (err); return status; } BOOL KeyFilesApply (HWND hwndDlg, Password *password, KeyFile *firstKeyFile, const char* volumeFileName) { 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; HiddenFilesPresentInKeyfilePath = FALSE; 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 keyfileData; SecurityToken::GetKeyfileData (SecurityTokenKeyfile (SingleStringToWide (kf->FileName)), keyfileData); if (keyfileData.empty()) { SetLastError (ERROR_HANDLE_EOF); handleWin32Error (hwndDlg, SRC_POS); Error ("ERR_PROCESS_KEYFILE", hwndDlg); 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) brea
/*
 Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.

 Governed by the TrueCrypt License 3.0 the full text of which is contained in
 the file License.txt included in TrueCrypt binary and source code distribution
 packages.
*/

#include "System.h"
#include "Application.h"
#include "FavoriteVolume.h"
#include "Xml.h"

namespace VeraCrypt
{
	FavoriteVolumeList FavoriteVolume::LoadList ()
	{
		FavoriteVolumeList favorites;

		FilePath path = Application::GetConfigFilePath (GetFileName());

		if (path.IsFile())
		{
			foreach (XmlNode node, XmlParser (path).GetNodes (L"volume"))
			{
				VolumeSlotNumber slotNumber = 0;
				wstring attr = wstring (node.Attributes[L"slotnumber"]);
				if (!attr.empty())
					slotNumber = StringConverter::ToUInt64 (attr);
	
				bool readOnly = false;
				attr = wstring (node.Attributes[L"readonly"]);
				if (!attr.empty())
					readOnly = (StringConverter::ToUInt32 (attr) != 0 ? true : false);

				bool system = false;
				attr = wstring (node.Attributes[L"system"]);
				if (!attr.empty())
					system = (StringConverter::ToUInt32 (attr) != 0 ? true : false);

				favorites.push_back (shared_ptr <FavoriteVolume> (
					new FavoriteVolume ((wstring) node.InnerText, wstring (node.Attributes[L"mountpoint"]), slotNumber, readOnly, system)));
			}
		}

		return favorites;
	}

	void FavoriteVolume::SaveList (const FavoriteVolumeList &favorites)
	{
		FilePath favoritesCfgPath = Application::GetConfigFilePath (GetFileName(), true);

		if (favorites.empty())
		{
			if (favoritesCfgPath.IsFile())
				favoritesCfgPath.Delete();
		}
		else
		{
			XmlNode favoritesXml (L"favorites");

			foreach_ref (const FavoriteVolume &favorite, favorites)
			{
				XmlNode node (L"volume", wstring (favorite.Path));
				node.Attributes[L"mountpoint"] = wstring (favorite.MountPoint);
				node.Attributes[L"slotnumber"] = StringConverter::FromNumber (favorite.SlotNumber);
				node.Attributes[L"readonly"] = StringConverter::FromNumber (favorite.ReadOnly ? 1 : 0);
				node.Attributes[L"system"] = StringConverter::FromNumber (favorite.System ? 1 : 0);

				favoritesXml.InnerNodes.push_back (node);
			}

			XmlWriter favoritesWriter (favoritesCfgPath);
			favoritesWriter.WriteNode (favoritesXml);
			favoritesWriter.Close();
		}
	}

	void FavoriteVolume::ToMountOptions (MountOptions &options) const
	{
		if (MountPoint.IsEmpty())
		{
			options.MountPoint.reset();
			options.NoFilesystem = true;
		}
		else
			options.MountPoint.reset (new DirectoryPath (MountPoint));

		options.Path.reset (new VolumePath (Path));
		options.PartitionInSystemEncryptionScope = System;
		options.Protection = (ReadOnly ? VolumeProtection::ReadOnly : VolumeProtection::None);
		options.SlotNumber = SlotNumber;
	}
}