summaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorFruhwirth Clemens <clemens-dated-1061728015.bf63@endorphin.org>2003-08-13 19:50:15 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-08-13 19:50:15 -0700
commit808ebd4ef703dd09277160a5056f59f176d41941 (patch)
tree28ec70cc199472f2089e06bea1f7c98ae34abb12 /drivers/block
parent0dd316cb36072ac94bf8f40d50ab57e5acf59599 (diff)
[PATCH] Fix cryptoloop ECB mode
cryptoloop won't oops anymore if ECB mode is requested.
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/cryptoloop.c77
1 files changed, 74 insertions, 3 deletions
diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
index d3ae3d00342d..40ddfe244ae2 100644
--- a/drivers/block/cryptoloop.c
+++ b/drivers/block/cryptoloop.c
@@ -79,20 +79,70 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info)
return err;
}
-typedef int (*encdec_t)(struct crypto_tfm *tfm,
+
+typedef int (*encdec_ecb_t)(struct crypto_tfm *tfm,
+ struct scatterlist *sg_out,
+ struct scatterlist *sg_in,
+ unsigned int nsg);
+
+
+static int
+cryptoloop_transfer_ecb(struct loop_device *lo, int cmd, char *raw_buf,
+ char *loop_buf, int size, sector_t IV)
+{
+ struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
+ struct scatterlist sg_out = { 0, };
+ struct scatterlist sg_in = { 0, };
+
+ encdec_ecb_t encdecfunc;
+ char const *in;
+ char *out;
+
+ if (cmd == READ) {
+ in = raw_buf;
+ out = loop_buf;
+ encdecfunc = tfm->crt_u.cipher.cit_decrypt;
+ } else {
+ in = loop_buf;
+ out = raw_buf;
+ encdecfunc = tfm->crt_u.cipher.cit_encrypt;
+ }
+
+ while (size > 0) {
+ const int sz = min(size, LOOP_IV_SECTOR_SIZE);
+
+ sg_in.page = virt_to_page(in);
+ sg_in.offset = (unsigned long)in & ~PAGE_MASK;
+ sg_in.length = sz;
+
+ sg_out.page = virt_to_page(out);
+ sg_out.offset = (unsigned long)out & ~PAGE_MASK;
+ sg_out.length = sz;
+
+ encdecfunc(tfm, &sg_out, &sg_in, sz);
+
+ size -= sz;
+ in += sz;
+ out += sz;
+ }
+
+ return 0;
+}
+
+typedef int (*encdec_cbc_t)(struct crypto_tfm *tfm,
struct scatterlist *sg_out,
struct scatterlist *sg_in,
unsigned int nsg, u8 *iv);
static int
-cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf,
+cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, char *raw_buf,
char *loop_buf, int size, sector_t IV)
{
struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
struct scatterlist sg_out = { 0, };
struct scatterlist sg_in = { 0, };
- encdec_t encdecfunc;
+ encdec_cbc_t encdecfunc;
char const *in;
char *out;
@@ -130,6 +180,27 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf,
return 0;
}
+static int
+cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf,
+ char *loop_buf, int size, sector_t IV)
+{
+ struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
+ if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB)
+ {
+ lo->transfer = cryptoloop_transfer_ecb;
+ return cryptoloop_transfer_ecb(lo, cmd, raw_buf, loop_buf, size, IV);
+ }
+ if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_CBC)
+ {
+ lo->transfer = cryptoloop_transfer_cbc;
+ return cryptoloop_transfer_cbc(lo, cmd, raw_buf, loop_buf, size, IV);
+ }
+
+ /* This is not supposed to happen */
+
+ printk( KERN_ERR "cryptoloop: unsupported cipher mode in cryptoloop_transfer!\n");
+ return -EINVAL;
+}
static int
cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg)