Hi, First some explanation. Most cryption algorithms initialize the cryption process with some init values, called IV (by me :-). This means that two identical clear messages will give different encrypted messages, if different IVs are used. The loop device supports different IVs; the IVs are initilized with the requested block number. I believe a better way is to use the requested sector number from CURRENT->sector. Using this value should make the encryption and decryption process completely independent from the underlying device. This is especially important when using a backing file. At the moment (as far as i heard) you can't use a backing file on a harddisk and then burn it to a CD, because the blocksize changes. Using sectors as atomic encryption unit should solve this problem. There is one drawback: The cryption algorithms have to know this semantic. At the moment most of the cryption algorithms use CBC mode to crypt a stream. When sector numbers are used as IV's the CBC mode has to be restarted periodically after 512 bytes with an incremented sector number as new IV's. (Please CC me if you want to comment :-) ) so long Ingo PS: Please have a look at the patch. It is against linux-2.4test9. I already mailed this patch to Alexander Kjeldaas who maintains the international crypto patch, but I don't know who maintains the loop device. (I know that it was originally written by Theodore Ts'o, but is he also the Maintainer ?) Please include the patch into the main tree...
--- linux-2.4test9/drivers/block/loop_old.c Tue Oct 10 14:25:10 2000 +++ linux-2.4test9/drivers/block/loop.c Tue Oct 10 16:09:11 2000 @@ -169,7 +169,7 @@ } static int lo_send(struct loop_device *lo, char *data, int len, loff_t pos, - int blksize) + int IV) { struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */ struct address_space *mapping = lo->lo_dentry->d_inode->i_mapping; @@ -182,7 +182,6 @@ index = pos >> PAGE_CACHE_SHIFT; offset = pos & (PAGE_CACHE_SIZE - 1); while (len > 0) { - int IV = index * (PAGE_CACHE_SIZE/blksize) + offset/blksize; size = PAGE_CACHE_SIZE - offset; if (size > len) size = len; @@ -221,7 +220,7 @@ struct lo_read_data { struct loop_device *lo; char *data; - int blksize; + int IV; }; static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) @@ -230,8 +229,8 @@ unsigned long count = desc->count; struct lo_read_data *p = (struct lo_read_data*)desc->buf; struct loop_device *lo = p->lo; - int IV = page->index * (PAGE_CACHE_SIZE/p->blksize) + offset/p->blksize; - + int IV = p->IV; + if (size > count) size = count; @@ -251,7 +250,7 @@ } static int lo_receive(struct loop_device *lo, char *data, int len, loff_t pos, - int blksize) + int IV) { struct file *file = lo->lo_backing_file; struct lo_read_data cookie; @@ -259,7 +258,7 @@ cookie.lo = lo; cookie.data = data; - cookie.blksize = blksize; + cookie.IV = IV; desc.written = 0; desc.count = len; desc.buf = (char*)&cookie; @@ -270,7 +269,7 @@ static void do_lo_request(request_queue_t * q) { - int block, offset, len, blksize, size; + int sector, block, offset, len, blksize, size; char *dest_addr; struct loop_device *lo; struct buffer_head *bh; @@ -296,8 +295,9 @@ } dest_addr = current_request->buffer; + sector = current_request->sector; len = current_request->current_nr_sectors << 9; - + blksize = BLOCK_SIZE; if (blksize_size[MAJOR(lo->lo_device)]) { blksize = blksize_size[MAJOR(lo->lo_device)][MINOR(lo->lo_device)]; @@ -348,7 +348,7 @@ if ((lo->transfer)(lo, current_request->cmd, bh->b_data + offset, - dest_addr, size, block)) { + dest_addr, size, sector)) { printk(KERN_ERR "loop: transfer error block %d\n", block); brelse(bh); @@ -371,10 +371,10 @@ pos = ((loff_t)current_request->sector << 9) + lo->lo_offset; spin_unlock_irq(&io_request_lock); if (current_request->cmd == WRITE) { - if (lo_send(lo, dest_addr, len, pos, blksize)) + if (lo_send(lo, dest_addr, len, pos, sector)) goto error_out_lock; } else { - if (lo_receive(lo, dest_addr, len, pos, blksize)) + if (lo_receive(lo, dest_addr, len, pos, sector)) goto error_out_lock; } done: