@@ -0,0 +1,1559 @@
+From a062df268df66641ed94d5c0e968e92c67b585e4 Mon Sep 17 00:00:00 2001
+From: Ludwig Nussel <ludwig.nussel@suse.de>
+Date: Thu, 29 Nov 2007 17:46:36 +0100
+Subject: [PATCH] losetup: support password hashing and specifying the key length
+
+* add support for password hashing (sha512, sha384, sha256, rmd160).
+* add support for loop-AES style strings like "twofish256" for
+ specifying the encryption algorithm and key length.
+
+Based on the SUSE patch from Ludwig Nussel <ludwig.nussel@suse.de>,
+this patch adds password hashing for cryptoloop devices. While
+cryptoloop is deprecated, users may still wish to access existing
+volumes.
+
+Incompatible change:
+ Default is now to hash using sha256, sha384 or sha512 depending
+ on key length (16, 24, or 32 bytes). Debian users will need to
+ specify "--phash rmd160" to access existing Debian devices.
+ Others will need to specify '--phash none'.
+
+sha512.c is from loop-AES.
+
+Signed-off-by: Ludwig Nussel <ludwig.nussel@suse.de>
+---
+
+ Makefile.am | 3
+ lomount.c | 174 +++++++++++++++++--
+ lomount.h | 5
+ losetup.8 | 11 +
+ mount.8 | 13 +
+ mount.c | 21 ++
+ rmd160.c | 532 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ rmd160.h | 11 +
+ sha512.c | 432 ++++++++++++++++++++++++++++++++++++++++++++++++
+ sha512.h | 45 +++++
+ 10 files changed, 1219 insertions(+), 28 deletions(-)
+
+diff --git a/mount/Makefile.am b/mount/Makefile.am
+index b0e6374..5d5a682 100644
+--- a/mount/Makefile.am
++++ b/mount/Makefile.am
+@@ -7,7 +7,8 @@ sbin_PROGRAMS = losetup swapon
+ dist_man_MANS = fstab.5 mount.8 swapoff.8 swapon.8 umount.8 losetup.8
+
+ # generic sources for all programs (mount, umount, losetup)
+-srcs_common = sundries.c xmalloc.c ../lib/canonicalize.c sundries.h xmalloc.h
++srcs_common = sundries.c xmalloc.c ../lib/canonicalize.c sundries.h xmalloc.h \
++ rmd160.c sha512.c
+
+ # generic header for mount and umount
+ hdrs_mount = fstab.h mount_mntent.h mount_constants.h \
+diff --git a/mount/lomount.c b/mount/lomount.c
+index 1b191ab..5c659cd 100644
+--- a/mount/lomount.c
++++ b/mount/lomount.c
+@@ -23,6 +23,12 @@
+ #include "sundries.h"
+ #include "xmalloc.h"
+ #include "pathnames.h"
++#include "rmd160.h"
++#include "sha512.h"
++
++#ifndef MIN
++#define MIN(a,b) ((a<b)?(a):(b))
++#endif
+
+ #define SIZE(a) (sizeof(a)/sizeof(a[0]))
+
+@@ -394,12 +400,22 @@ show_loop_fd(int fd, char *device) {
+
+ if (loopinfo64.lo_encrypt_type ||
+ loopinfo64.lo_crypt_name[0]) {
+- char *e = (char *)loopinfo64.lo_crypt_name;
++ const char *e = (const char*)loopinfo64.lo_crypt_name;
+
+ if (*e == 0 && loopinfo64.lo_encrypt_type == 1)
+ e = "XOR";
+- printf(_(", encryption %s (type %" PRIu32 ")"),
+- e, loopinfo64.lo_encrypt_type);
++ printf(_(", encryption %s (type %" PRIu32 "), key length %u"),
++ e, loopinfo64.lo_encrypt_type, loopinfo64.lo_encrypt_key_size);
++
++#if 0
++ if(loopinfo64.lo_encrypt_key_size) {
++ unsigned i;
++ printf("\nkey ");
++ for(i = 0; i < loopinfo64.lo_encrypt_key_size; ++i) {
++ printf("%hhx",loopinfo64.lo_encrypt_key[i]);
++ }
++ }
++#endif
+ }
+ printf("\n");
+ return 0;
+@@ -655,7 +671,7 @@ xgetpass(int pfd, const char *prompt) {
+ }
+
+ if (pass == NULL)
+- return "";
++ return NULL;
+
+ pass[i] = 0;
+ return pass;
+@@ -669,6 +685,24 @@ digits_only(const char *s) {
+ return 1;
+ }
+
++static void phash_none(const unsigned char *key, size_t keylen, unsigned char* buf, size_t buflen)
++{
++ memcpy(buf, key, MIN(buflen, keylen));
++}
++
++static void phash_rmd160(const unsigned char *key, size_t keylen, unsigned char* buf, size_t buflen)
++{
++ unsigned char tmpbuf[RMD160_HASH_SIZE*2];
++ unsigned char* tmp = malloc(keylen+1);
++ tmp[0]='A';
++ memcpy(tmp+1, key, keylen);
++ rmd160_hash_buffer(tmpbuf, key, keylen);
++ rmd160_hash_buffer(tmpbuf + RMD160_HASH_SIZE, tmp, keylen+1);
++ memset(tmp, 0, keylen+1);
++ free(tmp);
++ memcpy(buf, tmpbuf, MIN(buflen, sizeof(tmpbuf)));
++}
++
+ /*
+ * return codes:
+ * 0 - success
+@@ -677,10 +711,11 @@ digits_only(const char *s) {
+ */
+ int
+ set_loop(const char *device, const char *file, unsigned long long offset,
+- unsigned long long sizelimit, const char *encryption, int pfd, int *options) {
++ unsigned long long sizelimit, const char *encryption, const char *phash,
++ int pfd, int *options, int keysz) {
+ struct loop_info64 loopinfo64;
+ int fd, ffd, mode, i;
+- char *pass;
++ char *pass = NULL;
+ char *filename;
+
+ if (verbose) {
+@@ -718,13 +753,37 @@ set_loop(const char *device, const char *file, unsigned long long offset,
+ filename = (char *) file;
+ xstrncpy((char *)loopinfo64.lo_file_name, filename, LO_NAME_SIZE);
+
++ loopinfo64.lo_encrypt_key_size = 0;
++
+ if (encryption && *encryption) {
+- if (digits_only(encryption)) {
++ // a hint for suse users
++ if(!phash && (!strcmp(encryption, "twofishSL92") || (!strcmp(encryption, "twofish") && !keysz))) {
++ fprintf(stderr,"Switching to old S.u.S.E. loop_fish2 compatibility mode.\n");
++ fprintf(stderr, _("Warning: This mode is deprecated, support for it will be removed in the future.\n"));
++ loopinfo64.lo_encrypt_type = 3; // LO_CRYPT_FISH
++ } else if (digits_only(encryption)) {
+ loopinfo64.lo_encrypt_type = atoi(encryption);
+ } else {
+ loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
+- snprintf((char *)loopinfo64.lo_crypt_name, LO_NAME_SIZE,
++ // check for something like twofish256
++ unsigned len = strlen(encryption);
++ snprintf((char*)loopinfo64.lo_crypt_name, LO_NAME_SIZE,
+ "%s", encryption);
++ if(len > 3) {
++ if(isdigit(loopinfo64.lo_crypt_name[len-3])
++ && isdigit(loopinfo64.lo_crypt_name[len-2])
++ && isdigit(loopinfo64.lo_crypt_name[len-1])) {
++ loopinfo64.lo_encrypt_key_size = atoi((char*)&loopinfo64.lo_crypt_name[len-3]) >> 3;
++ loopinfo64.lo_crypt_name[len-3] = 0;
++ }
++ }
++
++ if(keysz && loopinfo64.lo_encrypt_key_size && loopinfo64.lo_encrypt_key_size != keysz >> 3) {
++ fprintf(stderr, _("please either specify '%s%d' or -e '%s' -k '%d'\n"),
++ loopinfo64.lo_crypt_name, loopinfo64.lo_encrypt_key_size<<3,
++ loopinfo64.lo_crypt_name, keysz);
++ return 1;
++ }
+ }
+ }
+
+@@ -745,20 +804,70 @@ set_loop(const char *device, const char *file, unsigned long long offset,
+ }
+ #endif
+
+- switch (loopinfo64.lo_encrypt_type) {
+- case LO_CRYPT_NONE:
+- loopinfo64.lo_encrypt_key_size = 0;
+- break;
+- case LO_CRYPT_XOR:
+- pass = getpass(_("Password: "));
+- goto gotpass;
+- default:
+- pass = xgetpass(pfd, _("Password: "));
+- gotpass:
++ if (loopinfo64.lo_encrypt_type != LO_CRYPT_NONE) {
++ void (*hfunc)(const unsigned char*, size_t, unsigned char*, size_t) = NULL;
++
|