diff --new-file -u -r linux-2.5.51.old/drivers/block/Kconfig linux-2.5.51/drivers/block/Kconfig --- linux-2.5.51.old/drivers/block/Kconfig Tue Dec 10 03:45:48 2002 +++ linux-2.5.51/drivers/block/Kconfig Mon Dec 30 19:00:57 2002 @@ -263,6 +263,14 @@ Most users will answer N here. +config BLK_DEV_CRYPTOLOOP + tristate "Cryptoloop Support + depends on BLK_DEV_LOOP + help + Say Y here if you want to be able to use the ciphers that are + provided by the CryptoAPI as loop transformation. This might be + used as hard disc encryption. + config BLK_DEV_NBD tristate "Network block device support" depends on NET diff --new-file -u -r linux-2.5.51.old/drivers/block/Makefile linux-2.5.51/drivers/block/Makefile --- linux-2.5.51.old/drivers/block/Makefile Mon Dec 30 19:00:24 2002 +++ linux-2.5.51/drivers/block/Makefile Fri Dec 27 21:56:46 2002 @@ -31,3 +31,4 @@ obj-$(CONFIG_BLK_DEV_UMEM) += umem.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o +obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o diff --new-file -u -r linux-2.5.51.old/drivers/block/cryptoloop.c linux-2.5.51/drivers/block/cryptoloop.c --- linux-2.5.51.old/drivers/block/cryptoloop.c Thu Jan 1 01:00:00 1970 +++ linux-2.5.51/drivers/block/cryptoloop.c Mon Dec 30 18:57:31 2002 @@ -0,0 +1,299 @@ +/* + Linux loop encryption enabling module + + $Id: cryptoloop.c,v 1.4 2002/08/17 22:55:47 hvr Exp $ + + Copyright (C) 2002 Herbert Valerio Riedel + + This module is a port to the Scatterlist CryptoAPI + by Fruhwirth Clemens + + This module is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This module is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this module; if not, write to the Free Software + + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if !defined(CONFIG_CRYPTOLOOP) +/* default options */ + +/* enable debugging features */ +/* #define CONFIG_CRYPTOLOOP_DEBUG */ + +#endif + +#include +#include + +#ifdef CONFIG_KMOD +#include +#endif + +#if !defined(LO_CRYPT_CRYPTOAPI) +// # warning LO_CRYPT_CRYPTOAPI not (yet) defined in kernel header +# define LO_CRYPT_CRYPTOAPI 18 +#endif + +#if !defined(CRYPTOLOOP_SET_BLKSIZE) +#define CRYPTOLOOP_SET_BLKSIZE 0X4CFC +#endif + +#if !defined(CRYPTOLOOP_SET_DEBUG) +#define CRYPTOLOOP_SET_DEBUG 0X4CFD +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef MODULE_LICENSE +MODULE_LICENSE ("GPL"); +#endif +#ifdef MODULE_DESCRIPTION +MODULE_DESCRIPTION ("loop blockdevice transferfunction adaptor / CryptoAPI"); +#endif +#ifdef MODULE_AUTHOR +MODULE_AUTHOR ("Herbert Valerio Riedel "); +#endif + + +#if !defined(LOOP_IV_SECTOR_SIZE) && defined(LO_IV_SECTOR_SIZE) +/* Adam J Richter's loop.c modifications */ +#define LOOP_IV_SECTOR_BITS LO_IV_SECTOR_BITS +#define LOOP_IV_SECTOR_SIZE LO_IV_SECTOR_SIZE +typedef lo_iv_t loop_iv_t; +#endif + +#if !defined(LOOP_IV_SECTOR_SIZE) && !defined(LOOP_IV_SECTOR_BITS) +# define LOOP_IV_SECTOR_BITS 9 +# define LOOP_IV_SECTOR_SIZE (1 << LOOP_IV_SECTOR_BITS) +typedef int loop_iv_t; +#endif + +/* assert (sizeof (cryptoloop_context) < sizeof (key_reserverd[48])) */ + + +struct cryptoloop_context { + int blocksize; + int debug; + spinlock_t spin; +}; + +static int +cryptoloop_init (struct loop_device *lo, struct loop_info *info) +{ + struct cryptoloop_context *lx = + (struct cryptoloop_context *) lo->key_reserved; + int err = -EINVAL; + char cipher[LO_NAME_SIZE]; + char *cp; + char *mode; + struct crypto_tfm *tfm=NULL; + + /* encryption breaks for non sector aligned offsets */ + if (info->lo_offset % LOOP_IV_SECTOR_SIZE) + goto out; + + lx->blocksize = LOOP_IV_SECTOR_SIZE; + lx->debug = 0; + lx->spin = SPIN_LOCK_UNLOCKED; + + strncpy (cipher, info->lo_name, LO_NAME_SIZE); + cipher[LO_NAME_SIZE - 1] = 0; + cp=cipher; + strsep(&cp,"-"); + mode=strsep(&cp,"-"); + + if(mode == NULL) + mode = "ecb"; + if(strcmp(mode,"cbc") == 0) + tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC); + else + if(strcmp(mode,"ecb") == 0) + tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB); + if(tfm == NULL) + return -EINVAL; + crypto_cipher_setkey(tfm, info->lo_encrypt_key, info->lo_encrypt_key_size); + + lo->key_data = tfm; + err = 0; + + out: + return err; +} + +typedef int (*encdec_t)(struct crypto_tfm *tfm, struct scatterlist *sg, + unsigned int nsg); + +static int +cryptoloop_transfer (struct loop_device *lo, int cmd, char *raw_buf, + char *loop_buf, int size, sector_t IV) +{ + const struct cryptoloop_context *lx = + (struct cryptoloop_context *) lo->key_reserved; + + struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; + struct scatterlist sg = { 0, }; + + encdec_t encdecfunc; + const int blocksize = lx->blocksize ? lx->blocksize : size; + char const *in; + char *out; + + if (cmd == READ) { + in = raw_buf; + out = loop_buf; + encdecfunc = crypto_cipher_decrypt; + } else { + in = loop_buf; + out = raw_buf; + encdecfunc = crypto_cipher_encrypt; + } + + /* + * scale IV back to custom (iv_)blocksize units + */ + + IV /= blocksize / LOOP_IV_SECTOR_SIZE; + + memcpy(out,in,size); + spin_lock(&(lx->spin)); + while (size > 0) { + const int _size = (size > blocksize) ? blocksize : size; + u32 iv[4] = { 0, }; + iv[0] = cpu_to_le32 (IV & 0xffffffff); + sg.page = virt_to_page(out); + sg.offset = (unsigned long)out & ~PAGE_MASK; + sg.length = _size; + crypto_cipher_set_iv(tfm, (void *)iv, crypto_tfm_alg_ivsize(tfm)); + encdecfunc(tfm, &sg, 1); + + IV++; + size -= _size; +// in += _size; + out += _size; + } + spin_unlock(&(lx->spin)); + + return 0; +} + +static int +cryptoloop_ioctl (struct loop_device *lo, int cmd, unsigned long arg) +{ + struct cryptoloop_context *lx = + (struct cryptoloop_context *) lo->key_reserved; + int err = -EINVAL; + int arg_int = 0; + + if (get_user (arg_int, (int *) arg)) + return -EFAULT; + + switch (cmd) { + + case CRYPTOLOOP_SET_BLKSIZE: + printk (KERN_DEBUG + "cryptoloop: switch to blocksize %d requested\n", + arg_int); + if (arg_int >= 0 && (arg_int % LOOP_IV_SECTOR_SIZE == 0)) { + lx->blocksize = arg_int; + err = 0; + } + break; + + case CRYPTOLOOP_SET_DEBUG: + printk (KERN_DEBUG "cryptoloop: set debug = %d requested\n", + arg_int); + lx->debug = arg_int; + err = 0; + break; + default: + err = -EINVAL; + break; + } + + return err; +} + +static int +cryptoloop_release (struct loop_device *lo) +{ + struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; + if (tfm != NULL) { + crypto_free_tfm(tfm); + lo->key_data = NULL; + return 0; + } + printk (KERN_ERR "cryptoloop_release(): cx == NULL ????\n"); + return -EINVAL; +} + +struct loop_func_table cryptoloop_funcs = { + number:LO_CRYPT_CRYPTOAPI, + init:cryptoloop_init, + ioctl:cryptoloop_ioctl, + transfer:cryptoloop_transfer, + release:cryptoloop_release +}; + +static int __init +init_cryptoloop (void) +{ + int rc; + + if ((rc = loop_register_transfer (&cryptoloop_funcs))) { + printk (KERN_ERR + "cryptoloop: register loop transfer function failed\n"); + return rc; + } + + printk (KERN_INFO "cryptoloop: loaded\n"); + return 0; +} + +static void __exit +cleanup_cryptoloop (void) +{ + if (loop_unregister_transfer (LO_CRYPT_CRYPTOAPI)) + printk (KERN_ERR + "cryptoloop: unregistering transfer funcs failed\n"); + + printk (KERN_INFO "cryptoloop: unloaded\n"); +} + +module_init (init_cryptoloop); +module_exit (cleanup_cryptoloop); + +EXPORT_NO_SYMBOLS; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 8 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -8 + * c-argdecl-indent: 8 + * c-label-offset: -8 + * c-continued-statement-offset: 8 + * c-continued-brace-offset: 0 + * End: + */