- what does it do
burn encrypted data on DVD using standard command (growisofs)
- how does it do what does
patch growisofs (from dvd+rw-tools):
file dvd+rw-tools-5.21.4.10.8.bacula.my.patch
file crypto.c
file loop.h
patch loop-AES 3.1:
file loop-aes-3.1.b-3.mypatch
Usage:
Assumptions:
DVD device: /dev/dvd
Key file: keyfile
losetup -e AES128 -K keyfile /dev/loop1 /dev/dvd
<Enter password>
growisofs -Z /dev/loop1 -R -J /some_file
growisofs -M /dev/loop1 -R -J /other_file
growisofs -free-space /dev/loop1
mount /dev/loop1 /media/cdrom
ls /media/cdrom/
- which way does it relate to the Bacula project
Save encrypted data backup on DVD
Sample Storage Daemon Configuration file fragment:
Device {
Name = "NEC ND-1300A"
Media Type = DVD
Archive Device = /dev/loop0 # <======= DVD encrypted device
LabelMedia = yes; # lets Bacula label unlabeled media
Random Access = Yes;
AutomaticMount = yes; # when device opened, read it
RemovableMedia = yes;
AlwaysOpen = no;
MaximumPartSize = 800M;
RequiresMount = yes;
MountPoint = /mnt/cdrom;
MountCommand = "/bin/mount -t iso9660 -o ro %a %m";
UnmountCommand = "/bin/umount %m";
SpoolDirectory = /tmp/backup;
WritePartCommand = "/etc/bacula/dvd-writepart %e %a %v"
FreeSpaceCommand = "/etc/bacula/dvd-freespace %a"
}
File: dvd+rw-tools-5.21.4.10.8.bacula.my.patch
--- growisofs.ORIG.c 2005-10-18 22:55:06.000000000 -0200
+++ growisofs.MYPATCH+BACULA.c 2005-10-19 15:32:23.159669000 -0200
@@ -315,12 +315,65 @@
* - Linux: fix for kernel version 2.6>=8, 2.6.8 itself is deficient,
* but the problem can be worked around by installing this version
* set-root-uid;
+ * 5.22: (by Nicolas Boichat, Bacula project)
+ * - Allow session to cross 4GB boundary regardless of medium type
+ * (don't need to have a DL media)
+ * - Add a -F option (used instead of -M or -Z), which displays
next_session
+ * offset and capacity (free space = next_session - capacity).
+ * 5.22cr: (by [EMAIL PROTECTED])
+ * Support to crypto DVD (both mode: -Z, -M) using
+ * loop-AES-v3.1b (Debian unstable) with my patch (included)
+ * - Usage:
+ * raw: growisofs -Z /dev/hdd ...
+ * crypto: growisofs -Z /dev/loop0 ...
+ * - This patch is not intended to be complete, elegant(aka Open BSD
design) or
+ * support all platforms
+ * - This patch is intended to be simple, easy to maintain (the Linux
way)
+ * - A better solution to this patched design: rewrite the
growisofs(harder)
+ * - Implemented mainly to support crypto DVD backup on Bacula project
+ * - Bacula & this patch:
+ * - this patch implement some deniability (dont trust me).
+ * - The bacula effort to use crypto data wont implement this
feature.
+ * It's out of Bacula project scope (I think). Deniability is out
+ * of scope on many projects.
+ * - This patch is a plus if you need some deniability
+ * (better support will be implemented. Maybe)
+ * - Current Bacula 1.37.40 dont implement crypto (File Store)
+ * - Test environment: this patch seems to be stable on this environment
+ * kernel: 2.6.11.12-xen0 patched to run XEN 2.0.7
+ * Distribution: Debian testing (Updated on 10/2005)
+ * DVD writer: [HL-DT-ST][DVDRAM GSA-4160B][A300]
+ * DVD Media ID: RICOHJPN/W11*, Sony (from dvd+rw-mediainfo command)
+ * Loop-aes: loop-AES-v3.1b with my patch, multi-key v3.
September 24 2005
+ * Backup: Bacula CVS 1.37.41 (testing)
+ * CPU: Atlhon XP 3200+, 1GRAM DDR400
+ * HD: 250GB+250GB
+ * (Steganographic store, loop-AES, boot from CDROM to mount
Steganographic store)
+ * Nobreak: APC SmartUPS 1400VA (+NUT)
+ * running 24x7
+ * - crypto.c: source code, platform dependent, crypto primitivies
+ * - TODO (maybe never implemented by me. And you???):
+ * - Inquiry Jari Ruusu from loop-aes to apply my patch
+ * - Change DVD with loop device mapped to dvd device
+ * (currently you need "losetup -d /dev/loop" to unlock dvd)
+ * Suggestions: Use ioctl LOOP_CHANGE_FD
+ * (change fd from dvd device to sparse file with 4.4GB
sized.
+ * I think this unlock DVD, not tested).
+ * - Debian package(growisofs, loop-AES)
+ * - DVD Steganographic store, Deniability
+ * (http://cube.dyndns.org/~rsnel/scubed/)
+ * - crypto.c, support: Linux/dm-crypt(Insecure), NetBSD(to run
XEN)
+ * - implement crypto as plugin (DLL or source code plugin)
+ * - This patch is experimental
+ * - I dont have time to maintain this code.
+ * But I think this is useful to others (Bacula Project ???)
+ *
*/
#define PRINT_VERSION(cmd) do { \
char *s=strrchr((cmd),'/'); \
s ? s++ : (s=(cmd)); \
printf ("* %.*sgrowisofs by <[EMAIL PROTECTED]>,"\
- " version 5.21,\n",(int)(s-(cmd)),(cmd)); \
+ " version 5.22,\n",(int)(s-(cmd)),(cmd)); \
} while (0)
#define _LARGEFILE_SOURCE
@@ -365,6 +418,12 @@
#define ENOMEDIUM ENODEV
#endif
+extern int get_in_fd_crp();
+extern int open_crypto_device(char **lo_device);
+extern ssize_t decrypt( void *buf, size_t nbyte, off64_t
offset);
+extern ssize_t pread64_crypto( int fildes, void *buf, size_t nbyte, off64_t
offset);
+extern ssize_t pwrite64_crypto(int fildes, void *buf, size_t nbyte, off64_t
offset);
+
typedef ssize_t (*pwrite64_t)(int,const void *,size_t,off64_t);
/*
* Symbols from growisofs_mmc.cpp
@@ -419,7 +478,7 @@ static void to_733 (unsigned char *s,uns
s[7] = (val) & 0xFF;
}
-static pwrite64_t pwrite64_method = pwrite64;
+pwrite64_t pwrite64_method = pwrite64;
/*
* Page-aligned 2*DVD_BLOCK=64KB large buffer, second 32KB contain
* "next" session volume descriptors that were written in the beginning
@@ -429,7 +488,8 @@ static char *the_buffer;
/*
* id_fd is passed to mkisofs, out_fd - to pwrite and ioctl_fd - to ioctl.
*/
-static int in_fd=-1,out_fd=-1;
+static int out_fd=-1;
+int in_fd=-1;
#ifndef INVALID_HANDLE
#define INVALID_HANDLE ((void *)-1)
@@ -1478,7 +1538,7 @@ int builtin_dd (int infd,int outfd,off64
progress->zero=time(NULL);
/* Write two 32KB chunks, not one 64KB... */
- if ((n=(*pwrite64_method) (outfd,the_buffer,DVD_BLOCK,outoff))
+ if ((n=pwrite64_crypto (outfd,the_buffer,DVD_BLOCK,outoff))
!= DVD_BLOCK)
{ if (n>0) errno = FATAL_START(EIO);
else if (n==0) errno = FATAL_START(ENOSPC);
@@ -1488,7 +1548,7 @@ int builtin_dd (int infd,int outfd,off64
outoff += DVD_BLOCK;
progress->current=outoff;
- if ((n=(*pwrite64_method)
(outfd,the_buffer+DVD_BLOCK,DVD_BLOCK,outoff))
+ if ((n=pwrite64_crypto
(outfd,the_buffer+DVD_BLOCK,DVD_BLOCK,outoff))
!= DVD_BLOCK)
{ if (n>0) errno = EIO;
else if (n==0) errno = ENOSPC;
@@ -1515,7 +1575,7 @@ int builtin_dd (int infd,int outfd,off64
{ off += n;
if (off == DVD_BLOCK)
{ off = 0;
- if ((n=(*pwrite64_method) (outfd,the_buffer,DVD_BLOCK,outoff))
+ if ((n=pwrite64_crypto (outfd,the_buffer,DVD_BLOCK,outoff))
!= DVD_BLOCK)
{ if (n>0) errno = EIO;
else if (n==0) errno = ENOSPC;
@@ -1528,7 +1588,7 @@ int builtin_dd (int infd,int outfd,off64
}
if (off) /* pad to the closest 32K is needed */
{ memset (the_buffer+off,0,DVD_BLOCK-off);
- if ((n=(*pwrite64_method) (outfd,the_buffer,DVD_BLOCK,outoff))
+ if ((n=pwrite64_crypto (outfd,the_buffer,DVD_BLOCK,outoff))
!= DVD_BLOCK)
{ if (n>0) errno = EIO;
else if (n==0) errno = ENOSPC;
@@ -1720,6 +1780,18 @@ int main (int argc, char *argv[])
else in_device = argv[++i];
dev_found = 'Z';
}
+ else if (argv[i][1] == 'F')
+ { if (len > 2) in_device = argv[i]+2;
+ else in_device = argv[++i];
+ dev_found = 'F';
+ dry_run = 1; /* NEVER write anything with -F */
+ }
+ else if (!strncmp(opt,"-free-space",11))
+ { if (len > 11) in_device = opt+11;
+ else in_device = argv[++i];
+ dev_found = 'F';
+ dry_run = 1; /* NEVER write anything with -F */
+ }
else if (!strcmp(opt,"-poor-man"))
{ if (poor_man<0) poor_man = 1;
continue;
@@ -1888,6 +1960,9 @@ int main (int argc, char *argv[])
}
}
+
+ open_crypto_device(&in_device);
+
/*
* Sets up in_fd, out_fd, ioctl_handle and poor_man variable.
* This procedure is platform-specific. If the program
@@ -1900,7 +1975,7 @@ int main (int argc, char *argv[])
if (mmc_profile&0x10000) /* blank media */
n=0, errno=EIO;
else
- { n=pread64 (in_fd,the_buffer,2048,VOLDESC_OFF*CD_BLOCK);
+ { n=pread64_crypto (in_fd,the_buffer,2048,VOLDESC_OFF*CD_BLOCK);
if (n==0) errno=EIO; /* end-of-file reached? */
}
if (n!=2048 && dev_found=='M')
@@ -1908,7 +1983,11 @@ int main (int argc, char *argv[])
fprintf (stderr," you most likely want to use -Z option.\n"),
exit (FATAL_START(errno));
- if (dev_found == 'M')
+ if ( (dev_found == 'M') ||
+ ((dev_found == 'F') && !(mmc_profile&0x10000)) &&
+ (the_buffer[0] || the_buffer[1] || the_buffer[2]))
+ /* -F : The medium is not blank, there is a fs on it
+ * (the_buffer[0,1 or 2] != 0), so compute next_session. */
{ if (memcmp (the_buffer,"\1CD001",6))
fprintf (stderr,":-( %s doesn't look like isofs...\n",
in_device), exit(FATAL_START(EMEDIUMTYPE));
@@ -1932,7 +2011,7 @@ int main (int argc, char *argv[])
exit(FATAL_START(EINVAL));
}
else if (next_session > (0x200000-0x5000)) /* 4GB/2K-40MB/2K */
- if ((mmc_profile&0xFFFF)!=0x2B || !no_4gb_check)
+ if (!no_4gb_check)
fprintf (stderr,":-( next session would cross 4GB "
"boundary, aborting...\n"),
exit (FATAL_START(ENOSPC));
@@ -1949,7 +2028,7 @@ int main (int argc, char *argv[])
# ifdef PASS_STDIN_TO_MKISOFS
M_parm = "/dev/fd/0";
# else
- sprintf (M_parm,"/dev/fd/%d",in_fd);
+ sprintf (M_parm,"/dev/fd/%d",get_in_fd_crp());
# endif
#endif
mkisofs_argv[mkisofs_argc++] = "-M";
@@ -1974,7 +2053,8 @@ int main (int argc, char *argv[])
exit (FATAL_START(EINVAL));
if (imgfd<0)
- { if (mkisofs_argc==1)
+ { if ((mkisofs_argc==1) && (dev_found != 'F'))
+
fprintf (stderr,"%s: no mkisofs options specified, "
"aborting...\n",argv[0]),
exit (FATAL_START(EINVAL));
@@ -2114,6 +2194,15 @@ int main (int argc, char *argv[])
}
}
+ if (dev_found == 'F') {
+ off64_t capacity = 0;
+ printf("next_session=%lld\n", next_session*CD_BLOCK);
+ if (ioctl_handle!=INVALID_HANDLE)
+ capacity = get_capacity (ioctl_handle);
+ printf("capacity=%lld\n", capacity);
+ exit(0);
+ }
+
if (imgfd>=0)
{ quiet--;
if (builtin_dd (imgfd,out_fd,next_session*CD_BLOCK) < 0)
@@ -2140,7 +2229,10 @@ int main (int argc, char *argv[])
if (next_session!=0 &&
(!poor_man || poor_man_rewritable (ioctl_handle,the_buffer)))
{
- descr = (struct iso_primary_descriptor *)the_buffer;
+
+ decrypt(the_buffer, DVD_BLOCK, DVD_BLOCK);
+
+ descr = (struct iso_primary_descriptor *)the_buffer;
if (memcmp (descr+16,"\1CD001",6))
fprintf (stderr,":-( %s:%d doesn't look like isofs!\n",
@@ -2152,7 +2244,7 @@ int main (int argc, char *argv[])
new_size = from_733(descr[16].volume_space_size) + next_session;
- if (!poor_man && (errno=0, pread64 (out_fd,descr,DVD_BLOCK,
+ if (!poor_man && (errno=0, pread64_crypto (out_fd,descr,DVD_BLOCK,
VOLDESC_OFF*CD_BLOCK)) != DVD_BLOCK)
errno=errno?errno:EIO,
perror (":-( unable to pread64(2) volume descriptors set"),
@@ -2178,7 +2270,7 @@ int main (int argc, char *argv[])
to_733(descr[i].volume_space_size,new_size);
}
- if ((*pwrite64_method) (out_fd,descr,DVD_BLOCK,
+ if (pwrite64_crypto (out_fd,descr,DVD_BLOCK,
VOLDESC_OFF*CD_BLOCK) != DVD_BLOCK)
perror (":-( unable to pwrite64(2) volume descriptors set"),
exit (errno);
File: crypto.c
/*
* File: crypto.c, contain platform dependent code
* Platform: Linux
* Crypto: loop-AES 3.1 with my patch
* Suggestions:
* - Implementation to other platforms (OpenBSD, Sun, Irix, ...)
* - Linux Cryptsetup (not recommended, serious security flaws)
* - implement this file as crypto plugin (DLL interface)
* Eg. plugin to Linux loop-AES, Linux cryptsetup, Sun, ...
* primitivies:
* open_crypto_device(), decrypt(), pread64_crypto() ...
*/
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <signal.h>
#include <poll.h>
#include <assert.h>
#include <sys/time.h>
#include <linux/loop.h>
#include "loop.h"
#define FATAL_START(err) (0x80|(err))
#define DVD_BLOCK 32768
typedef ssize_t (*pwrite64_t)(int,const void *,size_t,off64_t);
extern pwrite64_t pwrite64_method;
extern int in_fd;
static int fdcrp_crp = -1;
static char dev_dvd[256];
static char bufcrp[DVD_BLOCK];
static struct loop_info64 loopinfo64_crp;
int get_in_fd_crp()
{
return (fdcrp_crp < 0) ? in_fd : fdcrp_crp;
}
static int loop_info(int fd, struct loop_info64 *loopinfo64)
{
if (ioctl(fd, LOOP_GET_STATUS64, loopinfo64) == 0)
{
loopinfo64->lo_file_name[LO_NAME_SIZE-2] = '*';
loopinfo64->lo_file_name[LO_NAME_SIZE-1] = 0;
loopinfo64->lo_crypt_name[LO_NAME_SIZE-1] = 0;
}
else
return -1;
return 0;
}
int open_crypto_device(char **lo_device)
{
/* Try open as loop device. if fail device is a raw dvd device */
if ((fdcrp_crp = open64(*lo_device, O_RDWR|O_SYNC)) < 0)
{
return -1; /* Caller handle the error */
}
if(loop_info(fdcrp_crp, &loopinfo64_crp) < 0)
{
/* The device is a raw dvd. */
close(fdcrp_crp);
fdcrp_crp = -1;
return -1;
}
/* Change the loop device name with the raw device name (DVD device) */
strncpy(dev_dvd, (char *)loopinfo64_crp.lo_file_name, sizeof(dev_dvd));
printf("Using loop device: %s, DVD device: %s\n", *lo_device, dev_dvd);
*lo_device = dev_dvd;
return 0;
}
ssize_t decrypt(void *buf, size_t nbyte, off64_t offset)
{
struct loop_ioctl_transfer lo_transfer;
if(fdcrp_crp < 0)
return -1;
assert(nbyte <= DVD_BLOCK && nbyte > 0 && !(nbyte & 0x1ff));
lo_transfer.cmd = READ;
lo_transfer.size = sizeof(bufcrp);
lo_transfer.raw_buf = buf; /* in */
lo_transfer.loop_buf = bufcrp; /* out */
lo_transfer.rblock = offset / 512;
if (ioctl(fdcrp_crp, LOOP_TRANSFER, &lo_transfer) != 0)
{
fprintf(stderr, "Error decrypt()\n");
exit(-1);
}
memcpy(buf, bufcrp, nbyte);
return nbyte;
}
ssize_t pread64_crypto(int fildes, void *buf, size_t nbyte, off64_t offset)
{
size_t w, r;
r = pread(fildes, buf, nbyte, offset);
if(fdcrp_crp < 0)
return r;
if(r != nbyte)
return r; /* caller handle the error */
return decrypt(buf, nbyte, offset);
}
ssize_t pwrite64_crypto(int fildes, void *buf, size_t nbyte, off64_t offset)
{
size_t w, r;
struct loop_ioctl_transfer lo_transfer;
if(fdcrp_crp < 0)
return (*pwrite64_method)(fildes, buf, nbyte, offset);
assert(nbyte == DVD_BLOCK);
lo_transfer.cmd = WRITE;
lo_transfer.size = nbyte;
lo_transfer.raw_buf = bufcrp; /* out */
lo_transfer.loop_buf = buf; /* in */
lo_transfer.rblock = offset / 512;
if (ioctl(fdcrp_crp, LOOP_TRANSFER, &lo_transfer) != 0)
{
fprintf(stderr, "Error pwrite64_crypto()\n");
exit(-1);
}
return (*pwrite64_method)(fildes, bufcrp, nbyte, offset);
}
File: loop.h
#define LOOP_TRANSFER 0x4D00 /* FIXME */
struct loop_ioctl_transfer
{
int cmd;
int size;
char *raw_buf;
char *loop_buf;
unsigned long rblock;
};
#define READ 0
#define WRITE 1
File: loop-aes-3.1.b-3.mypatch
--- loop.c-2.6.patched.ORIG.c 2005-10-18 11:42:03.993133000 -0200
+++ loop.c-2.6.patched.NEW.c 2005-10-18 15:15:55.014263000 -0200
@@ -129,6 +129,19 @@
# define QUEUE_ORDERED_NONE 0
#endif
+#define LOOP_TRANSFER 0x4D00 /* FIXME */
+#define IOCTL_TRANSFER_SIZE 0x8000 /* 64 keys * 512 bytes/sector = 32kb =
0x8000 */
+struct loop_ioctl_transfer
+{
+ int cmd;
+ int size;
+ char *raw_buf;
+ char *loop_buf;
+ sector_t rblock;
+};
+static char **raw_buf_ioctl_arr = NULL;
+static char **loop_buf_ioctl_arr = NULL;
+
static int max_loop = 8;
module_param(max_loop, int, 0);
@@ -1707,6 +1720,62 @@ loop_get_status64(struct loop_device *lo
return err;
}
+static int
+loop_ioctl_transfer(struct loop_device *lo, struct loop_ioctl_transfer
*arg)
+{
+ char *lbuf, *rbuf;
+ unsigned int size, len;
+ struct loop_ioctl_transfer transfer;
+ int ret = 0;
+
+ if (copy_from_user(&transfer, arg, sizeof (struct loop_ioctl_transfer)))
+ return -EFAULT;
+
+ if(transfer.cmd != READ && transfer.cmd != WRITE)
+ return -EFAULT;
+
+ if(transfer.size != IOCTL_TRANSFER_SIZE)
+ return -EFAULT;
+
+ lbuf = raw_buf_ioctl_arr[lo->lo_number];
+ rbuf = loop_buf_ioctl_arr[lo->lo_number];
+
+ if(!lbuf)
+ {
+ /* FIXME: kfree */
+ lbuf = loop_buf_ioctl_arr[lo->lo_number] = kmalloc(transfer.size,
GFP_KERNEL);
+ if(!lbuf)
+ return -EFAULT;
+ }
+
+ if(!rbuf)
+ {
+ /* FIXME: kfree */
+ rbuf = raw_buf_ioctl_arr[lo->lo_number] = kmalloc(transfer.size,
GFP_KERNEL);
+ if(!rbuf)
+ return -EFAULT;
+ }
+
+ if(transfer.cmd == READ)
+ {
+ if (copy_from_user(rbuf, transfer.raw_buf, transfer.size))
+ return -EFAULT;
+ ret = lo_do_transfer(lo, transfer.cmd, rbuf, lbuf, transfer.size,
transfer.rblock);
+ if (copy_to_user(transfer.loop_buf, lbuf, transfer.size))
+ return -EFAULT;
+ }
+ else
+ {
+ if (copy_from_user(lbuf, transfer.loop_buf, transfer.size))
+ return -EFAULT;
+ ret = lo_do_transfer(lo, transfer.cmd, rbuf, lbuf, transfer.size,
transfer.rblock);
+ if (copy_to_user(transfer.raw_buf, rbuf, transfer.size))
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
static int lo_ioctl(struct inode *inode, struct file * file, unsigned int
cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
@@ -1756,6 +1825,9 @@ static int lo_ioctl(struct inode *inode,
case LOOP_RECOMPUTE_DEV_SIZE:
err = figure_loop_size(lo, bdev);
break;
+ case LOOP_TRANSFER:
+ err = loop_ioctl_transfer(lo, (struct loop_ioctl_transfer
*)arg);
+ break;
default:
err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
}
@@ -1863,6 +1935,19 @@ int __init loop_init(void)
if (!loop_dev_ptr_arr)
goto out_mem1;
+ raw_buf_ioctl_arr = kmalloc(max_loop * sizeof(char *), GFP_KERNEL);
+ if (!raw_buf_ioctl_arr)
+ goto out_mem1;
+ memset(raw_buf_ioctl_arr, 0, max_loop * sizeof(char *));
+ loop_buf_ioctl_arr = kmalloc(max_loop * sizeof(char *), GFP_KERNEL);
+ if (!loop_buf_ioctl_arr)
+ {
+ kfree(loop_dev_ptr_arr);
+ kfree(raw_buf_ioctl_arr);
+ goto out_mem1;
+ }
+ memset(loop_buf_ioctl_arr, 0, max_loop * sizeof(char *));
+
disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL);
if (!disks)
goto out_mem2;
-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.
Get Certified Today * Register for a JBoss Training Course
Free Certification Exam for All Training Attendees Through End of 2005
Visit http://www.jboss.com/services/certification for more information
_______________________________________________
Bacula-users mailing list
Bacula-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bacula-users