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

📄 volumes.c

📁 加密硬盘、分区、虚拟盘的程序源码
💻 C
字号:
/* Copyright (C) 2004 TrueCrypt Team, truecrypt.org
   This product uses components written by Paul Le Roux <pleroux@swprofessionals.com> */

#include "TCdefs.h"

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <time.h>

#include "crypto.h"
#include "random.h"
#include "endian.h"
#include "fat.h"
#include "volumes.h"

#include "pkcs5.h"
#include "crc.h"

void _cdecl
EncryptSector8 (unsigned long *data,
		unsigned __int64 secNo,
		unsigned long noSectors,
		unsigned char *ks,
		unsigned char *iv,
		int cipher)
{
	unsigned long sectorIV[2];
	unsigned long *IV = (unsigned long *) iv;
	unsigned __int64 *IV64 = (unsigned __int64 *) iv;
	unsigned long x1, x2;
	unsigned long j;

	while (noSectors--)
	{
		// Sector encryption is implemented by making IV unique for each
		// sector and obfuscating cipher text
		IV64[0] ^= secNo;
		IV64[1] ^= secNo;
		IV64[2] ^= secNo;

		sectorIV[0] = IV[0];
		sectorIV[1] = IV[1];

		x1 = crc32long ( &IV[2] ) ^ crc32long ( &IV[5] );
		x2 = crc32long ( &IV[3] ) ^ crc32long ( &IV[4] );

		IV64[0] ^= secNo;
		IV64[1] ^= secNo;
		IV64[2] ^= secNo;

		// CBC encrypt the entire sector
		for (j = 0; j < 64; j++)
		{
			// CBC
			data[0] ^= sectorIV[0];
			data[1] ^= sectorIV[1];

			encipher_block (cipher, data, ks);

			sectorIV[0] = data[0];
			sectorIV[1] = data[1];

			// Cipher text XOR
			data[0] ^= x1;
			data[1] ^= x2;

			data += 2;
		}

		secNo++;
	}
}

void
  _cdecl
DecryptSector8 (unsigned long *data,
		unsigned __int64 secNo,
		unsigned long noSectors,
		unsigned char *ks,
		unsigned char *iv,
		int cipher)
{
	unsigned long sectorIV[2];
	unsigned long *IV = (unsigned long *) iv;
	unsigned __int64 *IV64 = (unsigned __int64 *) iv;
	unsigned long x1, x2;
	int j;

	while (noSectors--)
	{
		IV64[0] ^= secNo;
		IV64[1] ^= secNo;
		IV64[2] ^= secNo;

		sectorIV[0] = IV[0];
		sectorIV[1] = IV[1];

		x1 = crc32long ( &IV[2] ) ^ crc32long ( &IV[5] );
		x2 = crc32long ( &IV[3] ) ^ crc32long ( &IV[4] );

		IV64[0] ^= secNo;
		IV64[1] ^= secNo;
		IV64[2] ^= secNo;

		// CBC decrypt the sector
		for (j = 0; j < 64; j++)
		{
			unsigned long a, b;

			// Cipher text XOR
			data[0] ^= x1;
			data[1] ^= x2;

			// CBC
			a = data[0];
			b = data[1];

			decipher_block (cipher, data, ks);

			data[0] ^= sectorIV[0];
			data[1] ^= sectorIV[1];

			sectorIV[0] = a;
			sectorIV[1] = b;

			data += 2;
		}

		secNo++;
	}
}

// EncryptBuffer
//
// Encrypts data in buffer
// Returns number of bytes encrypted
//
// len = length of data in bytes
int _cdecl 
EncryptBuffer (unsigned char *buf,
		unsigned long len,
		unsigned char *ks,
		unsigned char *iv,
		int cipher)
{
	unsigned long *data = (unsigned long *) buf;
	unsigned long *IV = (unsigned long *) iv;
	unsigned long bufIV[2];
	unsigned long j;

	len /= get_block_size (cipher);

	bufIV[0] = IV[0];
	bufIV[1] = IV[1];

	if (get_block_size (cipher) == 8)
	{
		/* CBC encrypt the buffer */
		for (j = 0; j < len; j++)
		{
			// CBC
			data[0] ^= bufIV[0];
			data[1] ^= bufIV[1];

			encipher_block (cipher, data, ks);

			bufIV[0] = data[0];
			bufIV[1] = data[1];

			// Cipher text XOR
			data[0] ^= IV[2];
			data[1] ^= IV[3];

			data += 2;
		}
	}
	else
		return 0;

	return len;
}

// DecryptBuffer
//
// Decrypts data in buffer
// Returns number of bytes encrypted
//
// len = length of data in bytes

int _cdecl
DecryptBuffer (unsigned char *buf,
		unsigned long len,
		unsigned char *ks,
		unsigned char *iv,
		int cipher)
{
	unsigned long *data = (unsigned long *)buf;
	unsigned long *IV = (unsigned long *) iv;
	unsigned long bufIV[2];
	unsigned long j;

	len /= get_block_size (cipher);

	bufIV[0] = IV[0];
	bufIV[1] = IV[1];

	if (get_block_size (cipher) == 8)
	{
		/* CBC encrypt the buffer */
		for (j = 0; j < len; j++)
		{
			unsigned long a, b;

			// Cipher text XOR
			data[0] ^= IV[2];
			data[1] ^= IV[3];

			// CBC
			a = data[0];
			b = data[1];

			decipher_block (cipher, data, ks);

			data[0] ^= bufIV[0];
			data[1] ^= bufIV[1];

			bufIV[0] = a;
			bufIV[1] = b;

			data += 2;
		}
	}
	else
		return 0;

	return len;
}

// Volume header structure:
//
// Offset	Length	Description
// ------------------------------------------
// Unencrypted:
// 0		64		Key salt
// Encrypted:
// 64		4		Magic 'TRUE'
// 68		2		Header version
// 70		2		Required program version
// 72		4		CRC32 of disk IV and key
// 76		8		Volume creation time
// 84		8		Header creation time
// 92		164		unused
// 256		32		Disk IV
// 288		224		Disk key

int
VolumeReadHeader (char *encryptedHeader, char *lpszPassword, PCRYPTO_INFO * retInfo)
{
	char header[SECTOR_SIZE];
	unsigned char *input = (unsigned char *) header;
	KEY_INFO keyInfo;
	PCRYPTO_INFO cryptoInfo;
	int nStatus = 0, nKeyLen;
	char dk[DISKKEY_SIZE];
	int pkcs5;
	int headerVersion, requiredVersion;
	
	cryptoInfo = *retInfo = crypto_open ();
	if (cryptoInfo == NULL)
		return ERR_OUTOFMEMORY;

	crypto_loadkey (&keyInfo, lpszPassword, strlen (lpszPassword));

	// PKCS5 is used to derive header key and IV from user password
	memcpy (keyInfo.key_salt, encryptedHeader + HEADER_USERKEY_SALT, USERKEY_SALT_SIZE);
	keyInfo.noIterations = USERKEY_ITERATIONS;		
	pkcs5 = SHA1;

	if (pkcs5 == SHA1)
	{
		derive_sha_key (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
		USERKEY_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + MAX_CIPHER_KEY);
	}
	// IV for header decryption
	memcpy (cryptoInfo->iv, dk, DISK_IV_SIZE);

	// Test all available ciphers
	for (cryptoInfo->cipher = 1; cryptoInfo->cipher <= LAST_CIPHER_ID; cryptoInfo->cipher++)
	{
		// Copy header for decryption
		memcpy (header, encryptedHeader, SECTOR_SIZE);  
		input = header;

		// Try to decrypt header 
		init_cipher (cryptoInfo->cipher, dk + DISK_IV_SIZE, cryptoInfo->ks);

		DecryptBuffer (header + HEADER_ENCRYPTEDDATA, HEADER_ENCRYPTEDDATASIZE,
							cryptoInfo->ks, cryptoInfo->iv, cryptoInfo->cipher);

		input += HEADER_ENCRYPTEDDATA;

		// Magic
		if (mgetLong (input) != 'TRUE')
			continue;

		// Header version
		headerVersion = mgetWord (input);

		// Required program version
		requiredVersion = mgetWord (input);

		// Check CRC of disk IV and key
		if (mgetLong (input) != crc32 (header + HEADER_DISKKEY, DISKKEY_SIZE))
			continue;

		// Volume creation time
		((unsigned long *)(&cryptoInfo->volume_creation_time))[1] = mgetLong (input);
		((unsigned long *)(&cryptoInfo->volume_creation_time))[0] = mgetLong (input);

		// Header creation time
		((unsigned long *)(&cryptoInfo->header_creation_time))[1] = mgetLong (input);
		((unsigned long *)(&cryptoInfo->header_creation_time))[0] = mgetLong (input);

		// Password and cipher OK

		// Check the version required to handle this volume
		if (requiredVersion > VERSION_NUM)
			return ERR_NEW_VERSION_REQUIRED;

		// Disk key
		nKeyLen = DISKKEY_SIZE;
		memcpy (keyInfo.key, header + HEADER_DISKKEY, nKeyLen);

		memcpy (cryptoInfo->master_decrypted_key, keyInfo.key, nKeyLen);
		memcpy (cryptoInfo->key_salt, keyInfo.key_salt, USERKEY_SALT_SIZE);
		cryptoInfo->pkcs5 = pkcs5;
		cryptoInfo->noIterations = keyInfo.noIterations;

		// Init with decrypted master disk key for sector decryption
		init_cipher (cryptoInfo->cipher, keyInfo.key + DISK_IV_SIZE, cryptoInfo->ks);

		// Disk IV
		memcpy (cryptoInfo->iv, keyInfo.key, DISK_IV_SIZE);

		/* Clear out the temp. key buffer */
		burn (dk, sizeof(dk));

		cryptoInfo->encrypt_sector = &EncryptSector8;
		cryptoInfo->decrypt_sector = &DecryptSector8;
	
		return 0;
	}

	crypto_close(cryptoInfo);
	burn (&keyInfo, sizeof (keyInfo));
	return ERR_PASSWORD_WRONG;
}

#ifndef DEVICE_DRIVER

#ifdef VOLFORMAT
extern HWND hDiskKey;
extern HWND hKeySalt;
#endif

// VolumeWriteHeader:
// Creates volume header in memory
int
VolumeWriteHeader (char *header, int cipher, char *lpszPassword,
		   int pkcs5, char *masterKey, unsigned __int64 volumeCreationTime, PCRYPTO_INFO * retInfo )
{
	unsigned char *p = (unsigned char *) header;
	KEY_INFO keyInfo;

	int nUserKeyLen = strlen(lpszPassword);
	PCRYPTO_INFO cryptoInfo = crypto_open ();
	char dk[DISKKEY_SIZE];
	int x;

	if (cryptoInfo == NULL)
		return ERR_OUTOFMEMORY;

	memset (header, 0, SECTOR_SIZE);

	//// Encryption setup

	// User key
	memcpy (keyInfo.userKey, lpszPassword, nUserKeyLen);
	keyInfo.keyLength = nUserKeyLen;
	keyInfo.noIterations = USERKEY_ITERATIONS;

	// User selected encryption algorithm
	cryptoInfo->cipher = cipher;

	// Salt for header key derivation 
	RandgetBytes (keyInfo.key_salt, USERKEY_SALT_SIZE);

	// PKCS5 is used to derive header key and IV from user password
	if (pkcs5 == SHA1)
	{
		derive_sha_key (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
				USERKEY_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + MAX_CIPHER_KEY );
	}

	// Generate disk key and IV
	if(masterKey == 0)
		RandgetBytes (keyInfo.key, DISKKEY_SIZE);
	else
		memcpy(keyInfo.key, masterKey, DISKKEY_SIZE);


	//// Header setup

	// Salt
	mputBytes (p, keyInfo.key_salt, USERKEY_SALT_SIZE);	

	// Magic
	mputLong (p, 'TRUE');

	// Header version
	mputWord (p, 0x0001);

	// Required program version to handle this volume
	mputWord (p, VOLUME_VERSION_NUM);

	// CRC of disk key
	x = crc32(keyInfo.key, DISKKEY_SIZE);
	mputLong (p, x);

	// Time
	{
		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);

		// Password change time
		GetLocalTime (&st);
		SystemTimeToFileTime (&st, &ft);
		mputLong (p, ft.dwHighDateTime);
		mputLong (p, ft.dwLowDateTime);
	}

	// Disk key and IV
	memcpy (header + HEADER_DISKKEY, keyInfo.key, DISKKEY_SIZE);


	//// Header encryption

	memcpy (cryptoInfo->iv, dk, DISK_IV_SIZE);
	init_cipher (cryptoInfo->cipher, dk + DISK_IV_SIZE, cryptoInfo->ks);

	EncryptBuffer (header + HEADER_ENCRYPTEDDATA, HEADER_ENCRYPTEDDATASIZE, 
			cryptoInfo->ks, cryptoInfo->iv, cryptoInfo->cipher);


	//// cryptoInfo setup for further use (disk format)

	// Init with master disk key for sector decryption
	init_cipher (cryptoInfo->cipher, keyInfo.key + DISK_IV_SIZE, cryptoInfo->ks);

	// Disk IV
	memcpy (cryptoInfo->iv, keyInfo.key, DISK_IV_SIZE);

	// Clear out the temp. key buffer
	burn (dk, sizeof(dk));

	if (get_block_size(cipher) == 8)
	{
		cryptoInfo->encrypt_sector = &EncryptSector8;
		cryptoInfo->decrypt_sector = &DecryptSector8;
	}

#ifdef VOLFORMAT
	{
		char tmp[64];
		BOOL dots3 = FALSE;
		int i, j;

		j = get_key_size (cipher);

		if (j > 21)
		{
			dots3 = TRUE;
			j = 21;
		}

		tmp[0] = 0;
		for (i = 0; i < j; i++)
		{
			char tmp2[8] =
			{0};
			sprintf (tmp2, "%02X", (int) (unsigned char) keyInfo.key[i + DISK_IV_SIZE]);
			strcat (tmp, tmp2);
		}

		if (dots3 == TRUE)
		{
			strcat (tmp, "...");
		}


		SetWindowText (hDiskKey, tmp);

		tmp[0] = 0;
		for (i = 0; i < 20; i++)
		{
			char tmp2[8];
			sprintf (tmp2, "%02X", (int) (unsigned char) keyInfo.key_salt[i]);
			strcat (tmp, tmp2);
		}

		SetWindowText (hKeySalt, tmp);
	}
#endif

	burn (&keyInfo, sizeof (keyInfo));

	*retInfo = cryptoInfo;
	return 0;
}


#endif				/* !NT4_DRIVER */

⌨️ 快捷键说明

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