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

📄 dm-target.c

📁 truecrypt-4.2a-source-cod 文件虚拟磁盘源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
Copyright (c) 2004-2006 TrueCrypt Foundation. All rights reserved. 

Covered by TrueCrypt License 2.1 the full text of which is contained in the file
License.txt included in TrueCrypt binary and source code distribution archives. 
*/

#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/ctype.h>
#include <linux/device-mapper.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/version.h>
#include <linux/workqueue.h>
#include <dm.h>

#include "Tcdefs.h"
#include "Crypto.h"
#include "Tests.h"
#include "Dm-target.h"

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
#error Linux kernel 2.6.5 or later required
#endif

int trace_level = 0;

#define MSG_PREFIX "truecrypt: "
#define error(fmt, args...) printk(KERN_ERR MSG_PREFIX fmt, ## args)
#define trace(level, fmt, args...) level <= trace_level && printk(KERN_DEBUG MSG_PREFIX fmt, ## args)
#define dbg(fmt, args...) printk(KERN_DEBUG MSG_PREFIX fmt, ## args)

#define MIN_POOL_SIZE 16

#ifndef __GFP_NOMEMALLOC
#define __GFP_NOMEMALLOC 0
#endif

struct target_ctx
{
	struct dm_dev *dev;
	sector_t start;
	char *volume_path;
	mempool_t *bio_ctx_pool;
	mempool_t *pg_pool;
	unsigned long long read_only_start;
	unsigned long long read_only_end;
	unsigned long long mtime;
	unsigned long long atime;
	int flags;
	PCRYPTO_INFO ci;
};

struct bio_ctx
{
	struct dm_target *target;
	struct bio *orig_bio;
	atomic_t ref_count;
	u64 crypto_sector;
	int error;
	struct work_struct work;
};

static struct workqueue_struct *work_queue = NULL;
static kmem_cache_t *bio_ctx_cache = NULL;

#define READ_ONLY(tc) (tc->flags & TC_READ_ONLY)
#define HID_VOL_PROT(tc) (tc->flags & TC_HIDDEN_VOLUME_PROTECTION)


static int hex2bin (char *hex_string, u8 *byte_buf, int max_length)
{
	int i = 0, n;
	char s[3];
	s[2] = 0;

	while (i < max_length
		&& (s[0] = *hex_string++) 
		&& (s[1] = *hex_string++))
	{
		if (sscanf (s, "%x", &n) != 1)
			return 0;
		byte_buf[i++] = (u8) n;
	}

	return i;
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
static void *mempool_alloc_pg (gfp_t gfp_mask, void *pool_data)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12)
static void *mempool_alloc_pg (unsigned int gfp_mask, void *pool_data)
#else
static void *mempool_alloc_pg (int gfp_mask, void *pool_data)
#endif
{
	trace (3, "mempool_alloc_pg (%d, %p)\n", gfp_mask, pool_data);
	return alloc_page (gfp_mask);
}

static void mempool_free_pg (void *element, void *pool_data)
{
	trace (3, "mempool_free_pg (%p, %p)\n", element, pool_data);
	__free_page (element);
}

#endif // LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)


static void *malloc_wait (mempool_t *pool, int direction)
{
	void *p;
	trace (3, "malloc_wait\n");

	while (1)
	{
		p = mempool_alloc (pool, GFP_NOIO | __GFP_NOMEMALLOC);

		if (p)
			return p;

		trace (3, "blk_congestion_wait\n");
		blk_congestion_wait (direction, HZ / 50);
	}
}


static void wipe_args (unsigned int argc, char **argv)
{
	int i;
	for (i = 0; i < argc; i++)
	{
		if (argv[i] != NULL)
			burn (argv[i], strlen (argv[i]));
	}
}


static int truecrypt_ctr (struct dm_target *ti, unsigned int argc, char **argv)
{
	struct target_ctx *tc;
	int key_size;
	int error = -EINVAL;
	unsigned long long sector;

	trace (3, "truecrypt_ctr (%p, %d, %p)\n", ti, argc, argv);

	if (argc != TC_LAST_ARG + 1)
	{
		ti->error = "truecrypt: Usage: <start_sector> <sector_count> truecrypt <EA> <mode> <key> <key2/IV> <host_device> <sector_offset> <read_only_start> <read_only_end> <mtime> <atime> <flags> <volume_path>";
		return -EINVAL;
	}

	tc = kmalloc (sizeof (*tc), GFP_KERNEL);
	if (tc == NULL)
	{
		ti->error = "truecrypt: Cannot allocate target context";
		error = -ENOMEM;
		goto err;
	}
	memset (tc, 0, sizeof (*tc));

	tc->ci = crypto_open ();
	if (tc == NULL)
	{
		ti->error = "truecrypt: Cannot allocate crypto_info";
		error = -ENOMEM;
		goto err;
	}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
	tc->bio_ctx_pool = mempool_create_slab_pool (MIN_POOL_SIZE, bio_ctx_cache);
#else
	tc->bio_ctx_pool = mempool_create (MIN_POOL_SIZE, mempool_alloc_slab, mempool_free_slab, bio_ctx_cache);
#endif

	if (!tc->bio_ctx_pool)
	{
		ti->error = "truecrypt: Cannot create bio context memory pool";
		error = -ENOMEM;
		goto err;
	}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
	tc->pg_pool = mempool_create_page_pool (MIN_POOL_SIZE, 0);
#else
	tc->pg_pool = mempool_create (MIN_POOL_SIZE, mempool_alloc_pg, mempool_free_pg, NULL);
#endif
	if (!tc->pg_pool)
	{
		ti->error = "truecrypt: Cannot create page memory pool";
		error = -ENOMEM;
		goto err;
	}

	if (sscanf (argv[TC_ARG_SEC], "%llu", &sector) != 1)
	{
		ti->error = "truecrypt: Invalid device sector";
		goto err;
	}
	tc->start = sector;

	if (dm_get_device (ti, argv[TC_ARG_DEV], tc->start, ti->len, dm_table_get_mode (ti->table), &tc->dev))
	{
		ti->error = "truecrypt: Device lookup failed";
		goto err;
	}

	// Encryption algorithm
	tc->ci->ea = 0;
	if (sscanf (argv[TC_ARG_EA], "%d", &tc->ci->ea) != 1
		|| tc->ci->ea < EAGetFirst ()
		|| tc->ci->ea > EAGetCount ())
	{
		ti->error = "truecrypt: Invalid encryption algorithm";
		goto err;
	}

	// Mode of operation
	tc->ci->mode = 0;
	if (sscanf (argv[TC_ARG_MODE], "%d", &tc->ci->mode) != 1
		|| tc->ci->mode < 1
		|| tc->ci->mode >= INVALID_MODE)
	{
		ti->error = "truecrypt: Invalid mode of operation";
		goto err;
	}

	// Key
	key_size = EAGetKeySize (tc->ci->ea);
	if (hex2bin (argv[TC_ARG_KEY], tc->ci->master_key, key_size) != key_size)
	{
		ti->error = "truecrypt: Invalid key";
		goto err;
	}
	
	// EA init
	trace (2, "EAInit (%d, %p, %p)\n", tc->ci->ea, tc->ci->master_key, tc->ci->ks);
	if (EAInit (tc->ci->ea, tc->ci->master_key, tc->ci->ks) == ERR_CIPHER_INIT_FAILURE)
	{
		ti->error = "truecrypt: Encryption algorithm initialization failed";
		goto err;
	}

	// Key2 / IV
	if (hex2bin (argv[TC_ARG_IV], tc->ci->iv, sizeof (tc->ci->iv)) != sizeof (tc->ci->iv))
	{
		ti->error = "truecrypt: Invalid IV";
		goto err;
	}

	// Mode init	
	if (!EAInitMode (tc->ci))
	{
		ti->error = "truecrypt: Mode of operation initialization failed";
		goto err;
	}

	// Read-only start sector
	if (sscanf (argv[TC_ARG_RO_START], "%llu", &tc->read_only_start) != 1)
	{
		ti->error = "truecrypt: Invalid read-only start sector";
		goto err;
	}

	// Read-only end sector
	if (sscanf (argv[TC_ARG_RO_END], "%llu", &tc->read_only_end) != 1)
	{
		ti->error = "truecrypt: Invalid read-only end sector";
		goto err;
	}

	// Modification time
	if (sscanf (argv[TC_ARG_MTIME], "%llu", &tc->mtime) != 1)
	{
		ti->error = "truecrypt: Invalid modification time";
		goto err;
	}

	// Access time
	if (sscanf (argv[TC_ARG_ATIME], "%llu", &tc->atime) != 1)
	{
		ti->error = "truecrypt: Invalid access time";
		goto err;
	}

	// Flags
	if (sscanf (argv[TC_ARG_FLAGS], "%d", &tc->flags) != 1)
	{
		ti->error = "truecrypt: Invalid flags";
		goto err;
	}

	// Volume path
	tc->volume_path = kmalloc (strlen (argv[TC_ARG_VOL]) + 1, GFP_KERNEL);
	if (tc->volume_path == NULL)
	{
		ti->error = "truecrypt: Cannot allocate volume path buffer";
		error = -ENOMEM;
		goto err;
	}
	strcpy (tc->volume_path, argv[TC_ARG_VOL]);

	// Hidden volume
	if (tc->start > 1)
	{
		tc->ci->hiddenVolume = TRUE;
		tc->ci->hiddenVolumeOffset = tc->start * SECTOR_SIZE;
	}

	ti->private = tc;

	wipe_args (argc, argv);
	return 0;

err:
	if (tc)
	{
		if (tc->ci)
			crypto_close (tc->ci);
		if (tc->volume_path)
			kfree (tc->volume_path);
		if (tc->bio_ctx_pool)
			mempool_destroy (tc->bio_ctx_pool);
		if (tc->pg_pool)
			mempool_destroy (tc->pg_pool);
		kfree (tc);
	}

	wipe_args (argc, argv);
	return error;
}


static void truecrypt_dtr (struct dm_target *ti)
{
	struct target_ctx *tc = (struct target_ctx *) ti->private;

	trace (3, "truecrypt_dtr (%p)\n", ti);

	mempool_destroy (tc->bio_ctx_pool);
	mempool_destroy (tc->pg_pool);
	crypto_close (tc->ci);
	kfree(tc->volume_path);
	dm_put_device(ti, tc->dev);
	kfree(tc);
}

⌨️ 快捷键说明

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