📄 dm-target.c
字号:
/*
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", §or) != 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 + -