--- /dev/null
+diff -Nur util-linux-2.11b.orig/mount/Makefile util-linux-2.11b/mount/Makefile
+--- util-linux-2.11b.orig/mount/Makefile Mon Mar 5 01:38:53 2001
++++ util-linux-2.11b/mount/Makefile Wed Mar 28 11:41:40 2001
+@@ -24,7 +24,7 @@
+
+ MAYBE = pivot_root swapoff
+
+-LO_OBJS = lomount.o $(LIB)/xstrncpy.o
++LO_OBJS = lomount.o rmd160.o $(LIB)/xstrncpy.o
+ NFS_OBJS = nfsmount.o nfsmount_xdr.o nfsmount_clnt.o
+ GEN_FILES = nfsmount.h nfsmount_xdr.c nfsmount_clnt.c
+
+@@ -57,7 +57,7 @@
+ main_losetup.o: lomount.c
+ $(COMPILE) -DMAIN lomount.c -o $@
+
+-losetup: main_losetup.o $(LIB)/xstrncpy.o
++losetup: main_losetup.o rmd160.o $(LIB)/xstrncpy.o
+ $(LINK) $^ -o $@
+
+ mount.o umount.o nfsmount.o losetup.o fstab.o realpath.o sundries.o: sundries.h
+diff -Nur util-linux-2.11b.orig/mount/lomount.c util-linux-2.11b/mount/lomount.c
+--- util-linux-2.11b.orig/mount/lomount.c Thu Mar 15 11:09:58 2001
++++ util-linux-2.11b/mount/lomount.c Wed Mar 28 12:09:33 2001
+@@ -6,6 +6,11 @@
+ * - added Native Language Support
+ * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * - fixed strerr(errno) in gettext calls
++ * 2000-09-24 Marc Mutz <Marc@Mutz.com>
++ * - added long option names and the --pass-fd option to pass
++ * passphrases via fd's to losetup/mount. Used for encryption in
++ * non-interactive environments. The idea behind xgetpass() is stolen
++ * from GnuPG, v.1.0.3 (http://www.gnupg.org/).
+ */
+
+ #define PROC_DEVICES "/proc/devices"
+@@ -21,54 +26,60 @@
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <unistd.h>
++#include <limits.h>
+ #include <sys/ioctl.h>
+ #include <sys/stat.h>
+ #include <sys/mman.h>
+
+ #include "loop.h"
+ #include "lomount.h"
++#include "rmd160.h"
+ #include "xstrncpy.h"
+ #include "nls.h"
+
++#ifndef LO_CRYPT_CRYPTOAPI
++#define LO_CRYPT_CRYPTOAPI 18
++#endif
++
+ extern int verbose;
+ extern char *xstrdup (const char *s); /* not: #include "sundries.h" */
+ extern void error (const char *fmt, ...); /* idem */
+
++struct cipher_info
++{
++ const char *name;
++ int blocksize;
++ int keysize_mask;
++ int ivsize;
++ int key_schedule_size;
++};
++
++static int set_loop_passwd(struct loop_info *_loopinfo, int pfd, int keysz,
++ const char *encryption, int fd, int ffd);
++static int get_cipher_info(const char *name, struct cipher_info *res);
++static int name_to_id(const char *name);
++#ifdef MAIN
++static char *id_to_name(int fd);
++#endif
++
+ #ifdef LOOP_SET_FD
+ struct crypt_type_struct {
+ int id;
+ char *name;
++ int keylength;
+ } crypt_type_tbl[] = {
+- { LO_CRYPT_NONE, "no" },
+- { LO_CRYPT_NONE, "none" },
+- { LO_CRYPT_XOR, "xor" },
+- { LO_CRYPT_DES, "DES" },
+- { -1, NULL }
++ { LO_CRYPT_NONE, "no",0 },
++ { LO_CRYPT_NONE, "none",0 },
++ { LO_CRYPT_XOR, "xor",0 },
++ { LO_CRYPT_DES, "DES",8 },
++ { LO_CRYPT_FISH2, "twofish",20 },
++ { LO_CRYPT_BLOW, "blowfish",20 },
++ { LO_CRYPT_CAST128, "cast128",16 },
++ { LO_CRYPT_IDEA, "idea",16 },
++ { -1, NULL,0 }
+ };
+
+-static int
+-crypt_type (const char *name) {
+- int i;
+-
+- if (name) {
+- for (i = 0; crypt_type_tbl[i].id != -1; i++)
+- if (!strcasecmp (name, crypt_type_tbl[i].name))
+- return crypt_type_tbl[i].id;
+- }
+- return -1;
+-}
+-
+ #ifdef MAIN
+-static char *
+-crypt_name (int id) {
+- int i;
+-
+- for (i = 0; crypt_type_tbl[i].id != -1; i++)
+- if (id == crypt_type_tbl[i].id)
+- return crypt_type_tbl[i].name;
+- return "undefined";
+-}
+-
+ static int
+ show_loop (char *device) {
+ struct loop_info loopinfo;
+@@ -90,7 +101,7 @@
+ printf (_("%s: [%04x]:%ld (%s) offset %d, %s encryption\n"),
+ device, loopinfo.lo_device, loopinfo.lo_inode,
+ loopinfo.lo_name, loopinfo.lo_offset,
+- crypt_name (loopinfo.lo_encrypt_type));
++ id_to_name(loopinfo.lo_encrypt_type));
+ close (fd);
+
+ return 0;
+@@ -183,24 +194,64 @@
+ error(_(
+ "mount: Could not find any loop device, and, according to %s,\n"
+ " this kernel does not know about the loop device.\n"
+- " (If so, then recompile or `insmod loop.o'.)"),
++ " (If so, then recompile or `modprobe loop'.)"),
+ PROC_DEVICES);
+ else
+ error(_(
+ "mount: Could not find any loop device. Maybe this kernel does not know\n"
+- " about the loop device (then recompile or `insmod loop.o'), or\n"
++ " about the loop device (then recompile or `modprobe loop'), or\n"
+ " maybe /dev/loop# has the wrong major number?"));
+ } else
+ error(_("mount: could not find any free loop device"));
+ return 0;
+ }
+
++#define HASHLENGTH 20
++#define PASSWDBUFFLEN 130 /* getpass returns only max. 128 bytes, see man getpass */
++
++/* A function to read the passphrase either from the terminal or from
++ * an open file descriptor */
++static char *
++xgetpass (int pfd, const char *prompt)
++{
++ if (pfd < 0) /* terminal */
++ return (getpass(prompt));
++ else { /* file descriptor */
++ char *pass = NULL;
++ int buflen, i;
++
++ buflen=0;
++ for (i=0; ; i++) {
++ if (i >= buflen-1) {
++ /* we're running out of space in the buffer.
++ * Make it bigger: */
++ char *tmppass = pass;
++ buflen += 128;
++ pass = realloc(tmppass,buflen);
++ if (pass == NULL) {
++ /* realloc failed. Stop reading _now_. */
++ error("not enough memory while reading passphrase");
++ pass = tmppass; /* the old buffer hasn't changed */
++ break;
++ }
++ };
++ if ( read(pfd,pass+i, 1) != 1 || pass[i] == '\n' )
++ break;
++ }
++ if (pass == NULL)
++ return "";
++ else {
++ pass[i] = 0;
++ return pass;
++ }
++ }
++}
++
+ int
+ set_loop (const char *device, const char *file, int offset,
+- const char *encryption, int *loopro) {
++ const char *encryption, int pfd, int keysz, int *loopro) {
+ struct loop_info loopinfo;
+- int fd, ffd, mode, i;
+- char *pass;
++ int fd, ffd, mode, tried_old;
+
+ mode = (*loopro ? O_RDONLY : O_RDWR);
+ if ((ffd = open (file, mode)) < 0) {
+@@ -218,13 +269,10 @@
+ *loopro = (mode == O_RDONLY);
+
+ memset (&loopinfo, 0, sizeof (loopinfo));
+- xstrncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
+- if (encryption && (loopinfo.lo_encrypt_type = crypt_type (encryption))
+- < 0) {
+- fprintf (stderr, _("Unsupported encryption type %s\n"),
+- encryption);
+- return 1;
+- }
++ snprintf(loopinfo.lo_name, sizeof(loopinfo.lo_name),
++ "%s-cbc", encryption);
++ loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
++ loopinfo.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
+ loopinfo.lo_offset = offset;
+
+ #ifdef MCL_FUTURE
+@@ -240,24 +288,74 @@
+ }
+ #endif
+
+- switch (loopinfo.lo_encrypt_type) {
++ if (ioctl (fd, LOOP_SET_FD, ffd) < 0) {
++ perror ("ioctl: LOOP_SET_FD");
++ return 1;
++ }
++
++ tried_old = 0;
++again:
++ set_loop_passwd(&loopinfo, pfd, keysz, encryption, fd, ffd);
++
++ if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
++ /* Try again with old-style LO_CRYPT_XX if
++ new style LO_CRYPT_CRYPTOAPI ioctl didn't work */
++ if (tried_old) {
++ error("The cipher does not exist, or a cipher module "
++ "needs to be loaded into the kernel");
++ perror ("ioctl: LOOP_SET_STATUS");
++ goto out_ioctl;
++ }
++ strncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
++ loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
++ loopinfo.lo_encrypt_type = name_to_id (encryption);
++ tried_old = 1;
++ goto again;
++ }
++ close (fd);
++ close (ffd);
++ if (verbose > 1)
++ printf(_("set_loop(%s,%s,%d): success\n"),
++ device, file, offset);
++ return 0;
++out_ioctl:
++ (void) ioctl (fd, LOOP_CLR_FD, 0);
++ return 1;
++}
++
++int
++set_loop_passwd(struct loop_info *loopinfo, int pfd, int keysz,
++ const char *encryption, int fd, int ffd)
++{
++ int i;
++ int keylength;
++ char *pass;
++ char keybits[2*HASHLENGTH];
++ char passwdbuff[PASSWDBUFFLEN];
++ struct cipher_info info;
++
++ switch (loopinfo->lo_encrypt_type) {
+ case LO_CRYPT_NONE:
+- loopinfo.lo_encrypt_key_size = 0;
++ loopinfo->lo_encrypt_key_size = 0;
+ break;
+ case LO_CRYPT_XOR:
+- pass = getpass (_("Password: "));
+- xstrncpy (loopinfo.lo_encrypt_key, pass, LO_KEY_SIZE);
+- loopinfo.lo_encrypt_key_size = strlen(loopinfo.lo_encrypt_key);
++ /* WARNING: xgetpass() can return massive amounts of data,
++ * not only 128 bytes like the original getpass(3) */
++ pass = xgetpass (pfd,_("Password: "));
++ strncpy (loopinfo->lo_encrypt_key, pass, LO_KEY_SIZE);
++ loopinfo->lo_encrypt_key[LO_KEY_SIZE - 1] = 0;
++ loopinfo->lo_encrypt_key_size = strlen(loopinfo->lo_encrypt_key);
+ break;
+ case LO_CRYPT_DES:
+- pass = getpass (_("Password: "));
+- strncpy (loopinfo.lo_encrypt_key, pass, 8);
+- loopinfo.lo_encrypt_key[8] = 0;
+- loopinfo.lo_encrypt_key_size = 8;
++ printf(_("WARNING: Use of DES is depreciated.\n"));
++ pass = xgetpass (pfd,_("Password: "));
++ strncpy (loopinfo->lo_encrypt_key, pass, 8);
++ loopinfo->lo_encrypt_key[8] = 0;
++ loopinfo->lo_encrypt_key_size = 8;
+ pass = getpass (_("Init (up to 16 hex digits): "));
+ for (i = 0; i < 16 && pass[i]; i++)
+ if (isxdigit (pass[i])) {
+- loopinfo.lo_init[i >> 3] |= (pass[i] > '9' ?
++ loopinfo->lo_init[i >> 3] |= (pass[i] > '9' ?
+ (islower (pass[i]) ? toupper (pass[i]) :
+ pass[i])-'A'+10 : pass[i]-'0') << (i&7) * 4;
+ } else {
+@@ -266,29 +364,82 @@
+ return 1;
+ }
+ break;
++ case LO_CRYPT_FISH2:
++ case LO_CRYPT_BLOW:
++ case LO_CRYPT_IDEA:
++ case LO_CRYPT_CAST128:
++ pass = xgetpass(pfd, _("Password :"));
++ strncpy(passwdbuff+1,pass,PASSWDBUFFLEN-1);
++ passwdbuff[PASSWDBUFFLEN-1] = '\0';
++ passwdbuff[0] = 'A';
++ rmd160_hash_buffer(keybits,pass,strlen(pass));
++ rmd160_hash_buffer(keybits+HASHLENGTH,passwdbuff,strlen(pass)+1);
++ memcpy((char*)loopinfo->lo_encrypt_key,keybits,2*HASHLENGTH);
++ keylength=0;
++ for(i=0; crypt_type_tbl[i].id != -1; i++){
++ if(loopinfo->lo_encrypt_type == crypt_type_tbl[i].id){
++ keylength = crypt_type_tbl[i].keylength;
++ break;
++ }
++ }
++ loopinfo->lo_encrypt_key_size=keylength;
++ break;
++ case LO_CRYPT_CRYPTOAPI:
++ /* Give the kernel an opportunity to load the cipher */
++ (void) ioctl (fd, LOOP_SET_STATUS, loopinfo);
++ if (get_cipher_info(loopinfo->lo_name, &info) < 0) {
++ return 1;
++ }
++ if (keysz > 0 &&
++ !((1 << ((keysz / 8) - 1)) & info.keysize_mask)) {
++ error("The specified keysize is not supported by "
++ "the selected cipher");
++ keysz = 0;
++ }
++
++ while (keysz <= 0 ||
++ !((1 << ((keysz / 8) - 1)) & info.keysize_mask)) {
++ int i = 0;
++ int available = 0;
++ char keysize[200];
++ printf("Available keysizes (bits): ");
++ for (; i < 32; i++) {
++ if (info.keysize_mask & (1 << i)) {
++ printf("%d ", 8*(i+1));
++ available = 1;
++ }
++ }
++ if (!available) {
++ printf("none");
++ }
++ printf("\nKeysize: ");
++ fgets(keysize, sizeof(keysize), stdin);
++ keysz = atoi(keysize);
++ }
++
++ pass = xgetpass(pfd, _("Password :"));
++ strncpy(passwdbuff+1,pass,PASSWDBUFFLEN-1);
++ passwdbuff[PASSWDBUFFLEN-1] = '\0';
++ passwdbuff[0] = 'A';
++ rmd160_hash_buffer(keybits,pass,strlen(pass));
++ rmd160_hash_buffer(keybits+HASHLENGTH,passwdbuff,strlen(pass)+1);
++ memcpy((char*)loopinfo->lo_encrypt_key,keybits,2*HASHLENGTH);
++
++ loopinfo->lo_encrypt_key_size=keysz/8;
++
++ break;
+ default:
+ fprintf (stderr,
+ _("Don't know how to get key for encryption system %d\n"),
+- loopinfo.lo_encrypt_type);
+- return 1;
+- }
+- if (ioctl (fd, LOOP_SET_FD, ffd) < 0) {
+- perror ("ioctl: LOOP_SET_FD");
++ loopinfo->lo_encrypt_type);
+ return 1;
+ }
+- if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
+- (void) ioctl (fd, LOOP_CLR_FD, 0);
+- perror ("ioctl: LOOP_SET_STATUS");
+- return 1;
+- }
+- close (fd);
+- close (ffd);
+- if (verbose > 1)
+- printf(_("set_loop(%s,%s,%d): success\n"),
+- device, file, offset);
+- return 0;
++ return 0;
+ }
+
++
++
++
+ int
+ del_loop (const char *device) {
+ int fd;
+@@ -319,7 +470,7 @@
+
+ int
+ set_loop (const char *device, const char *file, int offset,
+- const char *encryption, int *loopro) {
++ const char *encryption, int pfd, int *loopro) {
+ mutter();
+ return 1;
+ }
+@@ -348,13 +499,40 @@
+ int verbose = 0;
+ static char *progname;
+
++static struct option longopts[] = {
++ { "delete", 0, 0, 'd' },
++ { "detach", 0, 0, 'd' },
++ { "encryption", 1, 0, 'e' },
++ { "help", 0, 0, 'h' },
++ { "offset", 1, 0, 'o' },
++ { "pass-fd", 1, 0, 'p' },
++ { "verbose", 0, 0, 'v' },
++ { "keybits", 1, 0, 'k' },
++ { NULL, 0, 0, 0 }
++};
++
++
+ static void
+ usage(void) {
+ fprintf(stderr, _("usage:\n\
+ %s loop_device # give info\n\
+ %s -d loop_device # delete\n\
+- %s [ -e encryption ] [ -o offset ] loop_device file # setup\n"),
+- progname, progname, progname);
++ %s [ options ] loop_device file # setup\n\
++ where options include\n\
++ --offset <num>, -o <num>\n\
++ start at offset <num> into file.\n\
++ --pass-fd <num>, -p <num>\n\
++ read passphrase from file descriptor <num>\n\
++ instead of the terminal.\n\
++ --encryption <cipher>, -e <cipher>\n\
++ encrypt with <cipher>.\n\
++ Check /proc/cipher for available ciphers.\n\
++ --keybits <num>, -k <num>\n\
++ specify number of bits in the hashed key given\n\
++ to the cipher. Some ciphers support several key\n\
++ sizes and might be more efficient with a smaller\n\
++ key size. Key sizes < 128 are generally not\n\
++ recommended\n"), progname, progname, progname);
+ exit(1);
+ }
+
+@@ -387,19 +565,22 @@
+
+ int
+ main(int argc, char **argv) {
+- char *offset, *encryption;
++ char *offset, *encryption, *passfd, *keysize;
+ int delete,off,c;
++ int pfd = -1;
+ int res = 0;
+ int ro = 0;
++ int keysz = 0;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ delete = off = 0;
+- offset = encryption = NULL;
++ offset = encryption = passfd = keysize = NULL;
+ progname = argv[0];
+- while ((c = getopt(argc,argv,"de:o:v")) != EOF) {
++ while ((c = getopt_long(argc,argv,"de:hk:o:p:v",
++ longopts, NULL)) != EOF) {
+ switch (c) {
+ case 'd':
+ delete = 1;
+@@ -407,9 +588,15 @@
+ case 'e':
+ encryption = optarg;
+ break;
++ case 'k':
++ keysize = optarg;
++ break;
+ case 'o':
+ offset = optarg;
+ break;
++ case 'p':
++ passfd = optarg;
++ break;
+ case 'v':
+ verbose = 1;
+ break;
+@@ -418,7 +605,7 @@
+ }
+ }
+ if (argc == 1) usage();
+- if ((delete && (argc != optind+1 || encryption || offset)) ||
++ if ((delete && (argc != optind+1 || encryption || offset || passfd)) ||
+ (!delete && (argc < optind+1 || argc > optind+2)))
+ usage();
+ if (argc == optind+1) {
+@@ -429,7 +616,12 @@
+ } else {
+ if (offset && sscanf(offset,"%d",&off) != 1)
+ usage();
+- res = set_loop(argv[optind],argv[optind+1],off,encryption,&ro);
++ if (passfd && sscanf(passfd,"%d",&pfd) != 1)
++ usage();
++ if (keysize && sscanf(keysize,"%d",&keysz) != 1)
++ usage();
++ res = set_loop(argv[optind], argv[optind+1], off,
++ encryption, pfd, keysz, &ro);
+ }
+ return res;
+ }
+@@ -445,3 +637,61 @@
+ }
+ #endif
+ #endif
++
++static int get_cipher_info(const char *name, struct cipher_info *res)
++{
++ char path[PATH_MAX];
++ char buf[2000];
++ FILE *f;
++ struct {
++ int *out;
++ const char *prefix;
++ } fields[] = {{&res->blocksize, "blocksize:"},
++ {&res->keysize_mask, "keysize_mask:"},
++ {&res->ivsize, "ivsize:"},
++ {&res->key_schedule_size, "key_schedule_size:"}};
++ snprintf(path, sizeof(path), "/proc/crypto/cipher/%s", name);
++ f = fopen(path, "r");
++ while(f && fgets(buf, sizeof(buf), f)) {
++ int i;
++ for (i = 0; i < sizeof(fields)/sizeof(fields[0]); i++) {
++ int len = strlen(fields[i].prefix);
++ if (strncmp(buf, fields[i].prefix, len) == 0) {
++ *fields[i].out = strtoul(&buf[len+1], NULL, 0);
++ break;
++ }
++ }
++
++ }
++ if (!f)
++ return -1;
++ return 0;
++}
++
++
++static int
++name_to_id(const char *name)
++{
++ int i;
++
++ if (name) {
++ for (i = 0; crypt_type_tbl[i].id != -1; i++)
++ if (!strcasecmp (name, crypt_type_tbl[i].name))
++ return crypt_type_tbl[i].id;
++ } else
++ return LO_CRYPT_NONE;
++ return LO_CRYPT_CRYPTOAPI;
++}
++
++#ifdef MAIN
++static char *
++id_to_name(int id) {
++ int i;
++
++ for (i = 0; crypt_type_tbl[i].id != -1; i++)
++ if (id == crypt_type_tbl[i].id)
++ return crypt_type_tbl[i].name;
++ return "undefined";
++}
++#endif
++
+diff -Nur util-linux-2.11b.orig/mount/lomount.h util-linux-2.11b/mount/lomount.h
+--- util-linux-2.11b.orig/mount/lomount.h Fri Dec 8 19:08:02 2000
++++ util-linux-2.11b/mount/lomount.h Wed Mar 28 11:38:53 2001
+@@ -1,5 +1,6 @@
+ extern int verbose;
+-extern int set_loop (const char *, const char *, int, const char *, int *);
++extern int set_loop (const char *, const char *, int, const char *,
++ int, int, int *);
+ extern int del_loop (const char *);
+ extern int is_loop_device (const char *);
+ extern char * find_unused_loop_device (void);
+diff -Nur util-linux-2.11b.orig/mount/losetup.8 util-linux-2.11b/mount/losetup.8
+--- util-linux-2.11b.orig/mount/losetup.8 Fri Aug 11 13:11:30 2000
++++ util-linux-2.11b/mount/losetup.8 Wed Mar 28 11:38:53 2001
+@@ -10,6 +10,9 @@
+ ] [
+ .B \-o
+ .I offset
++] [
++.B \-p
++.I num
+ ]
+ .I loop_device file
+ .br
+@@ -26,9 +29,9 @@
+ \fIloop_device\fP argument is given, the status of the corresponding loop
+ device is shown.
+ .SH OPTIONS
+-.IP \fB\-d\fP
++.IP "\fB\-\-delete, \-\-detach, \-d\fP"
+ detach the file or device associated with the specified loop device.
+-.IP "\fB\-e \fIencryption\fP"
++.IP "\fB\-\-encryption, \-e \fIencryption\fP"
+ .RS
+ enable data encryption. The following keywords are recognized:
+ .IP \fBNONE\fP
+@@ -36,16 +39,62 @@
+ .PD 0
+ .IP \fBXOR\fP
+ use a simple XOR encryption.
++.IP \fBAES\fP
++use Advanced Encryption Standard encryption. AES encryption is only available
++if you are using the international kernel and AES encryption has been enabled
++in the Crypto API.
++enabled in the Crypto API.
++.IP \fBBlowfish\fP
++use Blowfish encryption. Blowfish encryption is only available if you
++are using the international kernel and Blowfish encryption has been
++enabled in the Crypto API.
++.IP \fBTwofish\fP
++use Twofish encryption. Twofish encryption is only available if you
++are using the international kernel and Twofish encryption has been
++enabled in the Crypto API.
++.IP \fBCAST\fP
++use CAST encryption. CAST encryption is only available if you
++are using the international kernel and CAST encryption has been
++enabled in the Crypto API.
+ .IP \fBDES\fP
+ use DES encryption. DES encryption is only available if the optional
+ DES package has been added to the kernel. DES encryption uses an additional
+ start value that is used to protect passwords against dictionary
+-attacks.
++attacks. Use of DES is deprecated.
++.IP \fBDFC\fP
++use DFC encryption. DFC encryption is only available if you
++are using the international kernel and DFC encryption has been
++enabled in the Crypto API.
++.IP \fBIDEA\fP
++use IDEA encryption. IDEA encryption is only available if you
++are using the international kernel and IDEA encryption has been
++enabled in the Crypto API.
++.IP \fBMARS\fP
++use MARS encryption. MARS encryption is only available if you
++are using the international kernel and MARS encryption has been
++enabled in the Crypto API.
++.IP \fBRC5\fP
++use RC5 encryption. RC5 encryption is only available if you
++are using the international kernel and RC5 encryption has been
++enabled in the Crypto API.
++.IP \fBRC6\fP
++use RC6 encryption. RC6 encryption is only available if you
++are using the international kernel and RC6 encryption has been
++enabled in the Crypto API.
++.IP \fBSerpent\fP
++use Serpent encryption. Serpent encryption is only available if you
++are using the international kernel and Serpent encryption has been
++enabled in the Crypto API.
+ .PD
+ .RE
+-.IP "\fB\-o \fIoffset\fP"
++.IP "\fB\-\-offset, \-o \fIoffset\fP"
+ the data start is moved \fIoffset\fP bytes into the specified file or
+ device.
++.IP "\fB\-\-pass-fd, \-p \fInum\fP"
++read the passphrase from file descriptor \fInum\fP instead of the
++terminal.
++.IP "\fB\-\-keybits, \-k \fInum\fP"
++set the number of bits to use in key to \fInum\fP.
+ .SH RETURN VALUE
+ .B losetup
+ returns 0 on success, nonzero on failure. When
+@@ -58,6 +107,7 @@
+ .SH FILES
+ .nf
+ /dev/loop0,/dev/loop1,... loop devices (major=7)
++/proc/cipher/* available ciphers
+ .fi
+ .SH EXAMPLE
+ If you are using the loadable module you must have the module loaded
+@@ -69,9 +119,8 @@
+ .nf
+ .IP
+ dd if=/dev/zero of=/file bs=1k count=100
+-losetup -e des /dev/loop0 /file
+-Password:
+-Init (up to 16 hex digits):
++losetup -e blowfish /dev/loop0 /file
++Password :
+ mkfs -t ext2 /dev/loop0 100
+ mount -t ext2 /dev/loop0 /mnt
+ ...
+@@ -85,8 +134,12 @@
+ # rmmod loop
+ .LP
+ .fi
+-.SH RESTRICTION
+-DES encryption is painfully slow. On the other hand, XOR is terribly weak.
++.SH RESTRICTIONS
++DES encryption is painfully slow. On the other hand, XOR is terribly
++weak. Both are insecure nowadays. Some ciphers require a licence for
++you to be allowed to use them.
++.SH BUGS
++CAST, DES, RC5 and Twofish are currently broken and cannot be used.
+ .SH AUTHORS
+ .nf
+ Original version: Theodore Ts'o <tytso@athena.mit.edu>
+diff -Nur util-linux-2.11b.orig/mount/mount.8 util-linux-2.11b/mount/mount.8
+--- util-linux-2.11b.orig/mount/mount.8 Mon Mar 19 22:21:28 2001
++++ util-linux-2.11b/mount/mount.8 Wed Mar 28 11:38:53 2001
+@@ -252,6 +252,12 @@
+ .B \-v
+ Verbose mode.
+ .TP
++.B \-p "\fInum\fP"
++If the mount requires a passphrase to be entered, read it from file
++descriptor
++.IR num\fP
++instead of from the terminal.
++.TP
+ .B \-a
+ Mount all filesystems (of the given types) mentioned in
+ .IR fstab .
+@@ -517,6 +523,15 @@
+ .BR noexec ", " nosuid ", and " nodev
+ (unless overridden by subsequent options, as in the option line
+ .BR user,exec,dev,suid ).
++.TP
++.B encryption
++Specifies an encryption algorithm to use. Used in conjunction with the
++.BR loop " option."
++.TP
++.B keybits
++Specifies the key size to use for an encryption algorithm. Used in conjunction
++with the
++.BR loop " and " encryption " options."
+ .RE
+
+ .SH "FILESYSTEM SPECIFIC MOUNT OPTIONS"
+@@ -1349,7 +1364,10 @@
+ .BR loop ", " offset " and " encryption ,
+ that are really options to
+ .BR losetup (8).
+-If no explicit loop device is mentioned
++If the mount requires a passphrase, you will be prompted for one unless
++you specify a file descriptor to read from instead with the
++.BR \-\-pass-fd
++option. If no explicit loop device is mentioned
+ (but just an option `\fB\-o loop\fP' is given), then
+ .B mount
+ will try to find some unused loop device and use that.
+diff -Nur util-linux-2.11b.orig/mount/mount.c util-linux-2.11b/mount/mount.c
+--- util-linux-2.11b.orig/mount/mount.c Thu Mar 15 11:09:59 2001
++++ util-linux-2.11b/mount/mount.c Wed Mar 28 12:10:45 2001
+@@ -107,6 +107,12 @@
+ /* True if ruid != euid. */
+ static int suid = 0;
+
++/* Contains the fd no. to read the passphrase from, if any */
++static int pfd = -1;
++
++/* Contains the preferred keysize in bits we want to use */
++static int keysz = 0;
++
+ /* Map from -o and fstab option strings to the flag argument to mount(2). */
+ struct opt_map {
+ const char *opt; /* option name */
+@@ -568,7 +574,8 @@
+ if (verbose)
+ printf(_("mount: going to use the loop device %s\n"), *loopdev);
+ offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0;
+- if (set_loop (*loopdev, *loopfile, offset, opt_encryption, &loopro)) {
++ if (set_loop (*loopdev, *loopfile, offset, opt_encryption, pfd,
++ keysz, &loopro)) {
+ if (verbose)
+ printf(_("mount: failed setting up loop device\n"));
+ return EX_FAIL;
+@@ -1281,6 +1288,8 @@
+ { "read-write", 0, 0, 'w' },
+ { "rw", 0, 0, 'w' },
+ { "options", 1, 0, 'o' },
++ { "pass-fd", 1, 0, 'p' },
++ { "keybits", 1, 0, 'k' },
+ { "types", 1, 0, 't' },
+ { "bind", 0, 0, 128 },
+ { "replace", 0, 0, 129 },
+@@ -1313,7 +1322,7 @@
+ " mount --bind olddir newdir\n"
+ "A device can be given by name, say /dev/hda1 or /dev/cdrom,\n"
+ "or by label, using -L label or by uuid, using -U uuid .\n"
+- "Other options: [-nfFrsvw] [-o options].\n"
++ "Other options: [-nfFrsvw] [-o options] [-p num].\n"
+ "For many more details, say man 8 mount .\n"
+ ));
+ /*
+@@ -1329,6 +1338,8 @@
+ int c, result = 0, specseen;
+ char *options = NULL, *spec, *node;
+ char *volumelabel = NULL;
++ char *passfd = NULL;
++ char *keysize = NULL;
+ char *uuid = NULL;
+ string_list types = NULL;
+ struct mntentchn *mc;
+@@ -1349,7 +1360,7 @@
+ initproctitle(argc, argv);
+ #endif
+
+- while ((c = getopt_long (argc, argv, "afFhlL:no:rsU:vVwt:",
++ while ((c = getopt_long (argc, argv, "afFhlL:no:p:rsU:vVwt:",
+ longopts, NULL)) != EOF) {
+ switch (c) {
+ case 'a': /* mount everything in fstab */
+@@ -1364,6 +1375,9 @@
+ case 'h': /* help */
+ usage (stdout, 0);
+ break;
++ case 'k':
++ keysize = optarg;
++ break;
+ case 'l':
+ list_with_volumelabel = 1;
+ break;
+@@ -1379,6 +1393,9 @@
+ else
+ options = xstrdup(optarg);
+ break;
++ case 'p': /* read passphrase from given fd */
++ passfd = optarg;
++ break;
+ case 'r': /* mount readonly */
+ readonly = 1;
+ readwrite = 0;
+@@ -1466,6 +1483,11 @@
+ printf(_("mount: mounting %s\n"), spec);
+ } else
+ spec = NULL; /* just for gcc */
++
++ if (passfd && sscanf(passfd,"%d",&pfd) != 1)
++ die (EX_USAGE, _("mount: argument to --pass-fd or -p must be a number"));
++ if (keysize && sscanf(keysize,"%d",&keysz) != 1)
++ die (EX_USAGE, _("mount: argument to --keybits or -k must be a number"));
+
+ switch (argc+specseen) {
+ case 0:
+diff -Nur util-linux-2.11b.orig/mount/rmd160.c util-linux-2.11b/mount/rmd160.c
+--- util-linux-2.11b.orig/mount/rmd160.c Thu Jan 1 01:00:00 1970
++++ util-linux-2.11b/mount/rmd160.c Wed Mar 28 11:38:53 2001
+@@ -0,0 +1,532 @@
++/* rmd160.c - RIPE-MD160
++ * Copyright (C) 1998 Free Software Foundation, Inc.
++ */
++
++/* This file was part of GnuPG. Modified for use within the Linux
++ * mount utility by Marc Mutz <Marc@Mutz.com>. None of this code is
++ * by myself. I just removed everything that you don't need when all
++ * you want to do is to use rmd160_hash_buffer().
++ * My comments are marked with (mm). */
++
++/* GnuPG 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.
++ *
++ * GnuPG 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 program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */
++
++#include <string.h> /* (mm) for memcpy */
++#include <endian.h> /* (mm) for BIG_ENDIAN and BYTE_ORDER */
++#include "rmd160.h"
++
++/* (mm) these are used by the original GnuPG file. In order to modify
++ * that file not too much, we keep the notations. maybe it would be
++ * better to include linux/types.h and typedef __u32 to u32 and __u8
++ * to byte? */
++typedef unsigned int u32; /* taken from e.g. util-linux's minix.h */
++typedef unsigned char byte;
++
++typedef struct {
++ u32 h0,h1,h2,h3,h4;
++ u32 nblocks;
++ byte buf[64];
++ int count;
++} RMD160_CONTEXT;
++
++/****************
++ * Rotate a 32 bit integer by n bytes
++ */
++#if defined(__GNUC__) && defined(__i386__)
++static inline u32
++rol( u32 x, int n)
++{
++ __asm__("roll %%cl,%0"
++ :"=r" (x)
++ :"0" (x),"c" (n));
++ return x;
++}
++#else
++ #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
++#endif
++
++/*********************************
++ * RIPEMD-160 is not patented, see (as of 25.10.97)
++ * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
++ * Note that the code uses Little Endian byteorder, which is good for
++ * 386 etc, but we must add some conversion when used on a big endian box.
++ *
++ *
++ * Pseudo-code for RIPEMD-160
++ *
++ * RIPEMD-160 is an iterative hash function that operates on 32-bit words.
++ * The round function takes as input a 5-word chaining variable and a 16-word
++ * message block and maps this to a new chaining variable. All operations are
++ * defined on 32-bit words. Padding is identical to that of MD4.
++ *
++ *
++ * RIPEMD-160: definitions
++ *
++ *
++ * nonlinear functions at bit level: exor, mux, -, mux, -
++ *
++ * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15)
++ * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31)
++ * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47)
++ * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63)
++ * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79)
++ *
++ *
++ * added constants (hexadecimal)
++ *
++ * K(j) = 0x00000000 (0 <= j <= 15)
++ * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2))
++ * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3))
++ * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5))
++ * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7))
++ * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2))
++ * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3))
++ * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5))
++ * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7))
++ * K'(j) = 0x00000000 (64 <= j <= 79)
++ *
++ *
++ * selection of message word
++ *
++ * r(j) = j (0 <= j <= 15)
++ * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8
++ * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12
++ * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2
++ * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
++ * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12
++ * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2
++ * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13
++ * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14
++ * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
++ *
++ *
++ * amount for rotate left (rol)
++ *
++ * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8
++ * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12
++ * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5
++ * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12
++ * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
++ * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6
++ * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11
++ * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5
++ * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8
++ * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
++ *
++ *
++ * initial value (hexadecimal)
++ *
++ * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476;
++ * h4 = 0xC3D2E1F0;
++ *
++ *
++ * RIPEMD-160: pseudo-code
++ *
++ * It is assumed that the message after padding consists of t 16-word blocks
++ * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15.
++ * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left
++ * shift (rotate) over s positions.
++ *
++ *
++ * for i := 0 to t-1 {
++ * A := h0; B := h1; C := h2; D = h3; E = h4;
++ * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4;
++ * for j := 0 to 79 {
++ * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E;
++ * A := E; E := D; D := rol_10(C); C := B; B := T;
++ * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)]
++ [+] K'(j)) [+] E';
++ * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T;
++ * }
++ * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A';
++ * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T;
++ * }
++ */
++
++/* Some examples:
++ * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31
++ * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe
++ * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
++ * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36
++ * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc
++ * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b
++ * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189
++ * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb
++ * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528
++ */
++
++
++static void
++rmd160_init( RMD160_CONTEXT *hd )
++{
++ hd->h0 = 0x67452301;
++ hd->h1 = 0xEFCDAB89;
++ hd->h2 = 0x98BADCFE;
++ hd->h3 = 0x10325476;
++ hd->h4 = 0xC3D2E1F0;
++ hd->nblocks = 0;
++ hd->count = 0;
++}
++
++
++
++/****************
++ * Transform the message X which consists of 16 32-bit-words
++ */
++static void
++transform( RMD160_CONTEXT *hd, byte *data )
++{
++ u32 a,b,c,d,e,aa,bb,cc,dd,ee,t;
++ #if BYTE_ORDER == BIG_ENDIAN
++ u32 x[16];
++ { int i;
++ byte *p2, *p1;
++ for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) {
++ p2[3] = *p1++;
++ p2[2] = *p1++;
++ p2[1] = *p1++;
++ p2[0] = *p1++;
++ }
++ }
++ #else
++ #if 0
++ u32 *x =(u32*)data;
++ #else
++ /* this version is better because it is always aligned;
++ * The performance penalty on a 586-100 is about 6% which
++ * is acceptable - because the data is more local it might
++ * also be possible that this is faster on some machines.
++ * This function (when compiled with -02 on gcc 2.7.2)
++ * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec;
++ * [measured with a 4MB data and "gpgm --print-md rmd160"] */
++ u32 x[16];
++ memcpy( x, data, 64 );
++ #endif
++ #endif
++
++
++#define K0 0x00000000
++#define K1 0x5A827999
++#define K2 0x6ED9EBA1
++#define K3 0x8F1BBCDC
++#define K4 0xA953FD4E
++#define KK0 0x50A28BE6
++#define KK1 0x5C4DD124
++#define KK2 0x6D703EF3
++#define KK3 0x7A6D76E9
++#define KK4 0x00000000
++#define F0(x,y,z) ( (x) ^ (y) ^ (z) )
++#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) )
++#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) )
++#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) )
++#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) )
++#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \
++ a = rol(t,s) + e; \
++ c = rol(c,10); \
++ } while(0)
++
++ /* left lane */
++ a = hd->h0;
++ b = hd->h1;
++ c = hd->h2;
++ d = hd->h3;
++ e = hd->h4;
++ R( a, b, c, d, e, F0, K0, 0, 11 );
++ R( e, a, b, c, d, F0, K0, 1, 14 );
++ R( d, e, a, b, c, F0, K0, 2, 15 );
++ R( c, d, e, a, b, F0, K0, 3, 12 );
++ R( b, c, d, e, a, F0, K0, 4, 5 );
++ R( a, b, c, d, e, F0, K0, 5, 8 );
++ R( e, a, b, c, d, F0, K0, 6, 7 );
++ R( d, e, a, b, c, F0, K0, 7, 9 );
++ R( c, d, e, a, b, F0, K0, 8, 11 );
++ R( b, c, d, e, a, F0, K0, 9, 13 );
++ R( a, b, c, d, e, F0, K0, 10, 14 );
++ R( e, a, b, c, d, F0, K0, 11, 15 );
++ R( d, e, a, b, c, F0, K0, 12, 6 );
++ R( c, d, e, a, b, F0, K0, 13, 7 );
++ R( b, c, d, e, a, F0, K0, 14, 9 );
++ R( a, b, c, d, e, F0, K0, 15, 8 );
++ R( e, a, b, c, d, F1, K1, 7, 7 );
++ R( d, e, a, b, c, F1, K1, 4, 6 );
++ R( c, d, e, a, b, F1, K1, 13, 8 );
++ R( b, c, d, e, a, F1, K1, 1, 13 );
++ R( a, b, c, d, e, F1, K1, 10, 11 );
++ R( e, a, b, c, d, F1, K1, 6, 9 );
++ R( d, e, a, b, c, F1, K1, 15, 7 );
++ R( c, d, e, a, b, F1, K1, 3, 15 );
++ R( b, c, d, e, a, F1, K1, 12, 7 );
++ R( a, b, c, d, e, F1, K1, 0, 12 );
++ R( e, a, b, c, d, F1, K1, 9, 15 );
++ R( d, e, a, b, c, F1, K1, 5, 9 );
++ R( c, d, e, a, b, F1, K1, 2, 11 );
++ R( b, c, d, e, a, F1, K1, 14, 7 );
++ R( a, b, c, d, e, F1, K1, 11, 13 );
++ R( e, a, b, c, d, F1, K1, 8, 12 );
++ R( d, e, a, b, c, F2, K2, 3, 11 );
++ R( c, d, e, a, b, F2, K2, 10, 13 );
++ R( b, c, d, e, a, F2, K2, 14, 6 );
++ R( a, b, c, d, e, F2, K2, 4, 7 );
++ R( e, a, b, c, d, F2, K2, 9, 14 );
++ R( d, e, a, b, c, F2, K2, 15, 9 );
++ R( c, d, e, a, b, F2, K2, 8, 13 );
++ R( b, c, d, e, a, F2, K2, 1, 15 );
++ R( a, b, c, d, e, F2, K2, 2, 14 );
++ R( e, a, b, c, d, F2, K2, 7, 8 );
++ R( d, e, a, b, c, F2, K2, 0, 13 );
++ R( c, d, e, a, b, F2, K2, 6, 6 );
++ R( b, c, d, e, a, F2, K2, 13, 5 );
++ R( a, b, c, d, e, F2, K2, 11, 12 );
++ R( e, a, b, c, d, F2, K2, 5, 7 );
++ R( d, e, a, b, c, F2, K2, 12, 5 );
++ R( c, d, e, a, b, F3, K3, 1, 11 );
++ R( b, c, d, e, a, F3, K3, 9, 12 );
++ R( a, b, c, d, e, F3, K3, 11, 14 );
++ R( e, a, b, c, d, F3, K3, 10, 15 );
++ R( d, e, a, b, c, F3, K3, 0, 14 );
++ R( c, d, e, a, b, F3, K3, 8, 15 );
++ R( b, c, d, e, a, F3, K3, 12, 9 );
++ R( a, b, c, d, e, F3, K3, 4, 8 );
++ R( e, a, b, c, d, F3, K3, 13, 9 );
++ R( d, e, a, b, c, F3, K3, 3, 14 );
++ R( c, d, e, a, b, F3, K3, 7, 5 );
++ R( b, c, d, e, a, F3, K3, 15, 6 );
++ R( a, b, c, d, e, F3, K3, 14, 8 );
++ R( e, a, b, c, d, F3, K3, 5, 6 );
++ R( d, e, a, b, c, F3, K3, 6, 5 );
++ R( c, d, e, a, b, F3, K3, 2, 12 );
++ R( b, c, d, e, a, F4, K4, 4, 9 );
++ R( a, b, c, d, e, F4, K4, 0, 15 );
++ R( e, a, b, c, d, F4, K4, 5, 5 );
++ R( d, e, a, b, c, F4, K4, 9, 11 );
++ R( c, d, e, a, b, F4, K4, 7, 6 );
++ R( b, c, d, e, a, F4, K4, 12, 8 );
++ R( a, b, c, d, e, F4, K4, 2, 13 );
++ R( e, a, b, c, d, F4, K4, 10, 12 );
++ R( d, e, a, b, c, F4, K4, 14, 5 );
++ R( c, d, e, a, b, F4, K4, 1, 12 );
++ R( b, c, d, e, a, F4, K4, 3, 13 );
++ R( a, b, c, d, e, F4, K4, 8, 14 );
++ R( e, a, b, c, d, F4, K4, 11, 11 );
++ R( d, e, a, b, c, F4, K4, 6, 8 );
++ R( c, d, e, a, b, F4, K4, 15, 5 );
++ R( b, c, d, e, a, F4, K4, 13, 6 );
++
++ aa = a; bb = b; cc = c; dd = d; ee = e;
++
++ /* right lane */
++ a = hd->h0;
++ b = hd->h1;
++ c = hd->h2;
++ d = hd->h3;
++ e = hd->h4;
++ R( a, b, c, d, e, F4, KK0, 5, 8);
++ R( e, a, b, c, d, F4, KK0, 14, 9);
++ R( d, e, a, b, c, F4, KK0, 7, 9);
++ R( c, d, e, a, b, F4, KK0, 0, 11);
++ R( b, c, d, e, a, F4, KK0, 9, 13);
++ R( a, b, c, d, e, F4, KK0, 2, 15);
++ R( e, a, b, c, d, F4, KK0, 11, 15);
++ R( d, e, a, b, c, F4, KK0, 4, 5);
++ R( c, d, e, a, b, F4, KK0, 13, 7);
++ R( b, c, d, e, a, F4, KK0, 6, 7);
++ R( a, b, c, d, e, F4, KK0, 15, 8);
++ R( e, a, b, c, d, F4, KK0, 8, 11);
++ R( d, e, a, b, c, F4, KK0, 1, 14);
++ R( c, d, e, a, b, F4, KK0, 10, 14);
++ R( b, c, d, e, a, F4, KK0, 3, 12);
++ R( a, b, c, d, e, F4, KK0, 12, 6);
++ R( e, a, b, c, d, F3, KK1, 6, 9);
++ R( d, e, a, b, c, F3, KK1, 11, 13);
++ R( c, d, e, a, b, F3, KK1, 3, 15);
++ R( b, c, d, e, a, F3, KK1, 7, 7);
++ R( a, b, c, d, e, F3, KK1, 0, 12);
++ R( e, a, b, c, d, F3, KK1, 13, 8);
++ R( d, e, a, b, c, F3, KK1, 5, 9);
++ R( c, d, e, a, b, F3, KK1, 10, 11);
++ R( b, c, d, e, a, F3, KK1, 14, 7);
++ R( a, b, c, d, e, F3, KK1, 15, 7);
++ R( e, a, b, c, d, F3, KK1, 8, 12);
++ R( d, e, a, b, c, F3, KK1, 12, 7);
++ R( c, d, e, a, b, F3, KK1, 4, 6);
++ R( b, c, d, e, a, F3, KK1, 9, 15);
++ R( a, b, c, d, e, F3, KK1, 1, 13);
++ R( e, a, b, c, d, F3, KK1, 2, 11);
++ R( d, e, a, b, c, F2, KK2, 15, 9);
++ R( c, d, e, a, b, F2, KK2, 5, 7);
++ R( b, c, d, e, a, F2, KK2, 1, 15);
++ R( a, b, c, d, e, F2, KK2, 3, 11);
++ R( e, a, b, c, d, F2, KK2, 7, 8);
++ R( d, e, a, b, c, F2, KK2, 14, 6);
++ R( c, d, e, a, b, F2, KK2, 6, 6);
++ R( b, c, d, e, a, F2, KK2, 9, 14);
++ R( a, b, c, d, e, F2, KK2, 11, 12);
++ R( e, a, b, c, d, F2, KK2, 8, 13);
++ R( d, e, a, b, c, F2, KK2, 12, 5);
++ R( c, d, e, a, b, F2, KK2, 2, 14);
++ R( b, c, d, e, a, F2, KK2, 10, 13);
++ R( a, b, c, d, e, F2, KK2, 0, 13);
++ R( e, a, b, c, d, F2, KK2, 4, 7);
++ R( d, e, a, b, c, F2, KK2, 13, 5);
++ R( c, d, e, a, b, F1, KK3, 8, 15);
++ R( b, c, d, e, a, F1, KK3, 6, 5);
++ R( a, b, c, d, e, F1, KK3, 4, 8);
++ R( e, a, b, c, d, F1, KK3, 1, 11);
++ R( d, e, a, b, c, F1, KK3, 3, 14);
++ R( c, d, e, a, b, F1, KK3, 11, 14);
++ R( b, c, d, e, a, F1, KK3, 15, 6);
++ R( a, b, c, d, e, F1, KK3, 0, 14);
++ R( e, a, b, c, d, F1, KK3, 5, 6);
++ R( d, e, a, b, c, F1, KK3, 12, 9);
++ R( c, d, e, a, b, F1, KK3, 2, 12);
++ R( b, c, d, e, a, F1, KK3, 13, 9);
++ R( a, b, c, d, e, F1, KK3, 9, 12);
++ R( e, a, b, c, d, F1, KK3, 7, 5);
++ R( d, e, a, b, c, F1, KK3, 10, 15);
++ R( c, d, e, a, b, F1, KK3, 14, 8);
++ R( b, c, d, e, a, F0, KK4, 12, 8);
++ R( a, b, c, d, e, F0, KK4, 15, 5);
++ R( e, a, b, c, d, F0, KK4, 10, 12);
++ R( d, e, a, b, c, F0, KK4, 4, 9);
++ R( c, d, e, a, b, F0, KK4, 1, 12);
++ R( b, c, d, e, a, F0, KK4, 5, 5);
++ R( a, b, c, d, e, F0, KK4, 8, 14);
++ R( e, a, b, c, d, F0, KK4, 7, 6);
++ R( d, e, a, b, c, F0, KK4, 6, 8);
++ R( c, d, e, a, b, F0, KK4, 2, 13);
++ R( b, c, d, e, a, F0, KK4, 13, 6);
++ R( a, b, c, d, e, F0, KK4, 14, 5);
++ R( e, a, b, c, d, F0, KK4, 0, 15);
++ R( d, e, a, b, c, F0, KK4, 3, 13);
++ R( c, d, e, a, b, F0, KK4, 9, 11);
++ R( b, c, d, e, a, F0, KK4, 11, 11);
++
++
++ t = hd->h1 + d + cc;
++ hd->h1 = hd->h2 + e + dd;
++ hd->h2 = hd->h3 + a + ee;
++ hd->h3 = hd->h4 + b + aa;
++ hd->h4 = hd->h0 + c + bb;
++ hd->h0 = t;
++}
++
++
++/* Update the message digest with the contents
++ * of INBUF with length INLEN.
++ */
++static void
++rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen)
++{
++ if( hd->count == 64 ) { /* flush the buffer */
++ transform( hd, hd->buf );
++ hd->count = 0;
++ hd->nblocks++;
++ }
++ if( !inbuf )
++ return;
++ if( hd->count ) {
++ for( ; inlen && hd->count < 64; inlen-- )
++ hd->buf[hd->count++] = *inbuf++;
++ rmd160_write( hd, NULL, 0 );
++ if( !inlen )
++ return;
++ }
++
++ while( inlen >= 64 ) {
++ transform( hd, inbuf );
++ hd->count = 0;
++ hd->nblocks++;
++ inlen -= 64;
++ inbuf += 64;
++ }
++ for( ; inlen && hd->count < 64; inlen-- )
++ hd->buf[hd->count++] = *inbuf++;
++}
++
++/* The routine terminates the computation
++ */
++
++static void
++rmd160_final( RMD160_CONTEXT *hd )
++{
++ u32 t, msb, lsb;
++ byte *p;
++
++ rmd160_write(hd, NULL, 0); /* flush */;
++
++ msb = 0;
++ t = hd->nblocks;
++ if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
++ msb++;
++ msb += t >> 26;
++ t = lsb;
++ if( (lsb = t + hd->count) < t ) /* add the count */
++ msb++;
++ t = lsb;
++ if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
++ msb++;
++ msb += t >> 29;
++
++ if( hd->count < 56 ) { /* enough room */
++ hd->buf[hd->count++] = 0x80; /* pad */
++ while( hd->count < 56 )
++ hd->buf[hd->count++] = 0; /* pad */
++ }
++ else { /* need one extra block */
++ hd->buf[hd->count++] = 0x80; /* pad character */
++ while( hd->count < 64 )
++ hd->buf[hd->count++] = 0;
++ rmd160_write(hd, NULL, 0); /* flush */;
++ memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
++ }
++ /* append the 64 bit count */
++ hd->buf[56] = lsb ;
++ hd->buf[57] = lsb >> 8;
++ hd->buf[58] = lsb >> 16;
++ hd->buf[59] = lsb >> 24;
++ hd->buf[60] = msb ;
++ hd->buf[61] = msb >> 8;
++ hd->buf[62] = msb >> 16;
++ hd->buf[63] = msb >> 24;
++ transform( hd, hd->buf );
++
++ p = hd->buf;
++ #if BYTE_ORDER == BIG_ENDIAN
++ #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \
++ *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0)
++ #else /* little endian */
++ #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
++ #endif
++ X(0);
++ X(1);
++ X(2);
++ X(3);
++ X(4);
++ #undef X
++}
++
++/****************
++ * Shortcut functions which puts the hash value of the supplied buffer
++ * into outbuf which must have a size of 20 bytes.
++ */
++void
++rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length )
++{
++ RMD160_CONTEXT hd;
++
++ rmd160_init( &hd );
++ rmd160_write( &hd, (byte*)buffer, length );
++ rmd160_final( &hd );
++ memcpy( outbuf, hd.buf, 20 );
++}
+diff -Nur util-linux-2.11b.orig/mount/rmd160.h util-linux-2.11b/mount/rmd160.h
+--- util-linux-2.11b.orig/mount/rmd160.h Thu Jan 1 01:00:00 1970
++++ util-linux-2.11b/mount/rmd160.h Wed Mar 28 11:38:53 2001
+@@ -0,0 +1,9 @@
++#ifndef RMD160_H
++#define RMD160_H
++
++void
++rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length );
++
++#endif /*RMD160_H*/
++
++