⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cli.c

📁 完美的虚拟加密文件系统程序。可以加密硬盘、优盘等
💻 C
📖 第 1 页 / 共 5 页
字号:
	int r;

	if (f == -1)
	{
		perror ("Cannot open /dev/random");
		return FALSE;
	}

	while ((r = read (f, buf++, 1)) == 1 && --len);

	if (r == -1)
	{
		perror ("Read from /dev/random failed");
		close (f);
		return FALSE;
	}

	if (len > 0)
	{
		perror ("Cannot read enough bytes from /dev/random");
		close (f);
		return FALSE;
	}

	close (f);
	return TRUE;
}


void HexDump (unsigned __int8 *data, unsigned int length)
{
	while (length--)
		printf ("%02x", (unsigned int) *data++);
}


double GetTime ()
{
	struct timeval tv;
	gettimeofday (&tv, NULL);

	return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
}


static __int64 TotalSectors, StartSector;
static double StartTime;
static double LastUpdateTime;


void InitProgressBar (__int64 totalSectors)
{
	LastUpdateTime = 0;
	StartTime = GetTime ();
	TotalSectors = totalSectors;
}


BOOL UpdateProgressBar (__int64 sector)
{
	unsigned __int64 s = sector - StartSector;
	double t = GetTime ();
	double elapsed = t - StartTime;
	unsigned __int64 bytesDone = (s + 1) * SECTOR_SIZE;
	unsigned __int64 bytesPerSec = bytesDone / (1 + elapsed);
	int timeRemain = (int)((TotalSectors  - s) / ((s + 1)/(elapsed + 1) + 1));

	if (DisplayProgress && IsTerminal && t - LastUpdateTime > 0.2)
	{
		printf ("\rDone: %.2f MB  Speed: %.2f MB/s  Left: %d:%02d:%02d  "
			, (double)bytesDone / 1024 / 1024
			, (double)bytesPerSec / 1024 / 1024
			, timeRemain / 3600
			, (timeRemain % 3600) / 60
			, (timeRemain % 3600) % 60);

		fflush (stdout);
		LastUpdateTime = t;
	}
}


static BOOL ParseSize (char *string, uint64_t *size)
{
	if (sscanf (string, "%lld", size) == 1)
	{
		if (strchr (string, 'k') || strchr (string, 'K'))
			*size *= 1024;
		else if (strchr (string, 'M'))
			*size *= 1024 * 1024;
		else if (strchr (string, 'G'))
			*size *= 1024 * 1024 * 1024;

		*size &= ~0x1FF;

		return TRUE;
	}
	return FALSE;
}


static BOOL CreateVolume (char *hostPath)
{
	PCRYPTO_INFO ci;
	char header[HEADER_SIZE];
	char path[MAX_PATH];
	char str[128];
	FILE *f;
	fatparams ft;
	Password *pw = &password;
	unsigned __int64 startSector, totalSectors, hostSize;
	BOOL hiddenVolume;
	int randReq;
	int i, r = 0;

	DropEffectiveUserId ();

	// Volume type
	switch (VolumeType)
	{
	case VOLUME_TYPE_NORMAL:
		hiddenVolume = FALSE;
		break;

	case VOLUME_TYPE_HIDDEN:
		hiddenVolume = TRUE;
		Quick = TRUE;
		break;

	default:
		puts ("Volume type:\n 1) Normal\n 2) Hidden");
		hiddenVolume = AskSelection (1, 1, 2) == 2;
		break;
	}

	// Host file or device
	hostPath = AskVolumePath (hostPath, hiddenVolume ? "Enter volume path" : "Enter file or device name for new volume");

	if (hiddenVolume)
	{
		if (!IsFile (hostPath) && !IsBlockDevice (hostPath))
		{
			error ("File or device %s does not exist. Hidden volume cannot be created.\n", hostPath);
			return FALSE;
		}
		f = fopen (hostPath, "r+b");
	}
	else if (IsFile (hostPath))
	{
		error ("File %s already exists.\n", hostPath);
		return FALSE;
	}
	else
	{
		f = fopen (hostPath, "wb");
	}

	if (!f)
	{
		perror ("Cannot open file or device");
		return FALSE;
	}

	EAMode = LRW;

	// Filesystem
	if (!Filesystem)
	{
		puts ("Filesystem:\n 1) FAT\n 2) None");
		Filesystem = AskSelection (1, 1, 2) == 1 ? "FAT" : "None";
	}

	// Host file/device size
	if (fseek (f, 0, SEEK_END) == -1 || (hostSize = ftello (f)) == (unsigned __int64)-1)
	{
		perror ("Cannot determine host file/device size");
		goto err;
	}

	// Volume size
	if (IsBlockDevice (hostPath) && !hiddenVolume)
	{
		if (VolumeSize != 0)
		{
			error ("Volume size cannot be changed for device-hosted volumes.\n");
			goto err;
		}

		VolumeSize = hostSize;
	}
	else if (VolumeSize == 0)
	{
		while (!AskString ("Enter volume size (bytes - size/sizeK/sizeM/sizeG)", str, sizeof (str))
			|| !ParseSize (str, &VolumeSize)
			|| VolumeSize == 0);
		puts ("");
	}

	if (hiddenVolume && VolumeSize > hostSize - MIN_VOLUME_SIZE )
	{
		error ("Outer volume too small for the size specified.\n");
		goto err;
	}

	if (strcasecmp ("FAT", Filesystem) == 0)
	{
		if (VolumeSize < MIN_VOLUME_SIZE || VolumeSize > MAX_FAT_VOLUME_SIZE)
		{
			error ("Specified volume size cannot be used with FAT filesystem.\n");
			goto err;
		}
	}

	// Hash algorithm
	if (HashAlgorithm == 0)
	{
		puts ("Hash algorithm:");

		for (i = 1; i <= LAST_PRF_ID; i++)
			printf ("%2d) %s\n", i, HashGetName (i));

		HashAlgorithm = AskSelection (1, 1, LAST_PRF_ID);
	}

	// Encryption algorithm
	if (EA == 0)
	{
		int max = 0;
ea:
		puts ("Encryption algorithm:");

		for (i = EAGetFirst (); i != 0; i = EAGetNext (i))
		{
			if (EAGetFirstMode (i) == LRW)
			{
				printf ("%2d) %s\n", i, EAGetName (str, i));
				max = i;
			}
		}

		EA = AskSelection (1, EAGetFirst (), max);

		if (CipherGetBlockSize (EAGetFirstCipher (EA)) == 8
			&& VolumeSize > WARN_VOL_SIZE_BLOCK64)
		{
			char s[3];

			AskString ("WARNING: You have selected a 64-bit block cipher. Due to security reasons,\n"
				"for this volume size, it is strongly recommended to select a 128-bit block cipher\n"
				"(for example, AES, Serpent, or Twofish) instead.\n\n"
				"Continue? [y/N]", s, sizeof (s));
			puts ("");

			if (strcmp (s, "y") && strcmp (s, "Y"))
				goto ea;
		}
	}

	randReq = EAGetKeySize (EA) * 2 + DISK_IV_SIZE * 2 + PKCS5_SALT_SIZE;

	// Password
	if (!CmdPasswordValid)
	{
		while (1)
		{
			AskPassword ("Enter password for new volume '%s': ", hostPath, &password);
			if (!DisplayPassword)
			{
				Password pv;
				AskPassword ("Re-enter 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 = &CmdPassword;

	if (FirstKeyFile && !KeyFilesApply (pw, FirstKeyFile, !UpdateTime))
	{
		error ("Error while processing keyfiles\n");
		goto err;
	}

	RandBytesFillRequired (randReq);

	// Create volume header
	r = VolumeWriteHeader (header,
		EA,
		EAMode,
		pw,
		HashAlgorithm,
		0,
		0,
		&ci,
		hiddenVolume ? VolumeSize : 0,
		FALSE);
	
	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;
	}

	totalSectors = VolumeSize / SECTOR_SIZE;
	ci->hiddenVolumeOffset = hostSize - VolumeSize - HIDDEN_VOL_HEADER_OFFSET;
	startSector = !hiddenVolume ? 1 : (ci->hiddenVolumeOffset / SECTOR_SIZE);

	if (DisplayKeys)
	{
		printf ("Master Key: ");
		HexDump (ci->master_key, EAGetKeySize (ci->ea));
		printf ("\nSecondary Key: ");
		HexDump (ci->iv, sizeof (ci->iv));
		puts ("\n");
	}

	// Write header
	if (hiddenVolume)
	{
		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;
	}

	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.");

	crypto_close (ci);
	fclose (f);
	return TRUE;

err:
	fclose (f);
	return FALSE;
}


static BOOL ChangePassword (char *volumePath)
{
	char header[HEADER_SIZE];
	char path[MAX_PATH];
	Password *pw = &password;
	PCRYPTO_INFO ci = NULL, ci2 = NULL;
	uint64_t startSector, totalSectors;
	time_t modTime = 0, acTime;
	int wipePass, ret = TRUE;
	int fd, r;
	FILE *f;

	// Volume path
	volumePath = AskVolumePath (volumePath, "Enter volume path");

	// Open volume
	if (!OpenVolume (volumePath, "Enter current password for '%s': ", volumePath, FALSE,
			&ci, &startSector, &totalSectors, &modTime, &acTime))
		return FALSE;

	// New password and/or keyfile(s)
	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 && !KeyFilesApply (pw, FirstNewKeyFile, !UpdateTime))
	{
		error ("Error while processing new keyfiles\n");
		return FALSE;
	}

	fd = open (volumePath, O_RDWR | O_SYNC);
	if (fd == -1)
	{
		perror ("Cannot open file or device");
		return FALSE;
	}
	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 (!wipeMode)
		{
			if (Verbose) puts ("\n");
			RandBytesFillRequired (PKCS5_SALT_SIZE);
		}

		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)
		{
			ret = FALSE;
			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");
			ret = FALSE;
			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");
				ret = FALSE;
				goto err;
			}
		}
		else
		{
			if (fseek (f, 0, SEEK_SET) == -1)
			{
				perror ("Cannot seek to volume header location");
				ret = FALSE;
				goto err;
			}
		}

		if (Verbose)
		{
			printf ("\rWriting header (pass %d)", wipePass);
			fflush (stdout);
		}

		if (fwrite (header, 1, HEADER_SIZE, f) != HEADER_SIZE)
		{
			perror ("Cannot write volume header");
			ret = FALSE;
			goto err;
		}

		fflush (f);
		fdatasync (fd);
	}

	printf ("%sPassword and/or keyfile(s) changed.\n", Verbose ? "\n" : "");

err:
	crypto_close (ci);
	close (fd);

	if (!UpdateTime && modTime != 0)
		RestoreFileTime (volumePath, modTime, acTime);

	return ret;
}


static BOOL BackupVolumeHeaders (char *backupFile, char *volumePath)
{
	char path[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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -