📄 dm-target.c
字号:
/* Copyright (c) 2004-2005 TrueCrypt Foundation. All rights reserved. Covered by TrueCrypt License 2.0 the full text of which is contained in the fileLicense.txt included in TrueCrypt binary and source code distribution archives. */#include <linux/bio.h>#include <linux/ctype.h>#include <linux/init.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#endifint 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 16struct target_ctx{ struct dm_dev *dev; sector_t start; char *volume_path; mempool_t *bio_ctx_pool; mempool_t *pg_pool; sector_t read_only_start; sector_t read_only_end; u64 mtime; u64 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 & FLAG_READ_ONLY)#define HID_VOL_PROT(tc) (tc->flags & FLAG_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; trace (3, "hex2bin (%p, %p, %d)\n", hex_string, byte_buf, max_length); 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,12)static void *mempool_alloc_pg (unsigned int gfp_mask, void *pool_data)#elsestatic 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);}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; trace (3, "truecrypt_ctr (%p, %d, %p)\n", ti, argc, argv); if (argc != 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; } tc->bio_ctx_pool = mempool_create (MIN_POOL_SIZE, mempool_alloc_slab, mempool_free_slab, bio_ctx_cache); if (!tc->bio_ctx_pool) { ti->error = "truecrypt: Cannot create bio context memory pool"; error = -ENOMEM; goto err; } tc->pg_pool = mempool_create (MIN_POOL_SIZE, mempool_alloc_pg, mempool_free_pg, NULL); if (!tc->pg_pool) { ti->error = "truecrypt: Cannot create page memory pool"; error = -ENOMEM; goto err; } if (sscanf (argv[ARG_SEC], SECTOR_FORMAT, &tc->start) != 1) { ti->error = "truecrypt: Invalid device sector"; goto err; } if (dm_get_device (ti, argv[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[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[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[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[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[ARG_RO_START], SECTOR_FORMAT, &tc->read_only_start) != 1) { ti->error = "truecrypt: Invalid read-only start sector"; goto err; } // Read-only end sector if (sscanf (argv[ARG_RO_END], SECTOR_FORMAT, &tc->read_only_end) != 1) { ti->error = "truecrypt: Invalid read-only end sector"; goto err; } // Modification time if (sscanf (argv[ARG_MTIME], "%Ld", &tc->mtime) != 1) { ti->error = "truecrypt: Invalid modification time"; goto err; } // Access time if (sscanf (argv[ARG_ATIME], "%Ld", &tc->atime) != 1) { ti->error = "truecrypt: Invalid access time"; goto err; } // Flags if (sscanf (argv[ARG_FLAGS], "%d", &tc->flags) != 1) { ti->error = "truecrypt: Invalid flags"; goto err; } // Volume path tc->volume_path = kmalloc (strlen (argv[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[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: trace (3, "truecrypt_ctr: error\n"); 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);}// Checks if two regions overlap (borders are parts of regions)static int RegionsOverlap (sector_t start1, sector_t end1, sector_t start2, sector_t end2){ return (start1 < start2) ? (end1 >= start2) : (start1 <= end2);}static void dereference_bio_ctx (struct bio_ctx *bc){ struct target_ctx *tc = (struct target_ctx *) bc->target->private; trace (3, "dereference_bio_ctx (%p)\n", bc); if (!atomic_dec_and_test (&bc->ref_count)) return; bio_endio (bc->orig_bio, bc->orig_bio->bi_size, bc->error); trace (3, "dereference_bio_ctx: mempool_free (%p)\n", bc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -