diff --git a/cryptsetup-2.13-crypto.diff b/cryptsetup-2.13-crypto.diff new file mode 100644 index 0000000..efade6d --- /dev/null +++ b/cryptsetup-2.13-crypto.diff @@ -0,0 +1,1486 @@ +* password hashing based on debian patch (rmd160, sha*) adds losetup options -k + and -H +* add support for loop-AES compatible strings like "twofish256" + +Signed-off-by: Ludwig Nussel + +Index: util-linux-ng-2.13rc2+git20070725/mount/Makefile.am +=================================================================== +--- util-linux-ng-2.13rc2+git20070725.orig/mount/Makefile.am ++++ util-linux-ng-2.13rc2+git20070725/mount/Makefile.am +@@ -12,7 +12,7 @@ headers_common = fstab.h linux_fs.h moun + mount_paths.h lomount.h fsprobe.h realpath.h xmalloc.h \ + getusername.h loop.h sundries.h + +-mount_common = fstab.c mount_mntent.c getusername.c lomount.c \ ++mount_common = fstab.c mount_mntent.c getusername.c lomount.c rmd160.c sha512.c \ + $(utils_common) $(headers_common) ../lib/env.c + + mount_SOURCES = mount.c $(mount_common) ../lib/setproctitle.c +@@ -25,7 +25,7 @@ umount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LD + + swapon_SOURCES = swapon.c swap_constants.h $(utils_common) + +-losetup_SOURCES = lomount.c loop.h lomount.h ++losetup_SOURCES = lomount.c loop.h lomount.h rmd160.c sha512.c + losetup_CPPFLAGS = -DMAIN $(AM_CPPFLAGS) + + mount_LDADD = $(LDADD_common) +Index: util-linux-ng-2.13rc2+git20070725/mount/rmd160.h +=================================================================== +--- /dev/null ++++ util-linux-ng-2.13rc2+git20070725/mount/rmd160.h +@@ -0,0 +1,11 @@ ++#ifndef RMD160_H ++#define RMD160_H ++ ++#define RMD160_HASH_SIZE 20 ++ ++void ++rmd160_hash_buffer( unsigned char *outbuf, const unsigned char *buffer, size_t length ); ++ ++#endif /*RMD160_H*/ ++ ++ +Index: util-linux-ng-2.13rc2+git20070725/mount/lomount.c +=================================================================== +--- util-linux-ng-2.13rc2+git20070725.orig/mount/lomount.c ++++ util-linux-ng-2.13rc2+git20070725/mount/lomount.c +@@ -20,9 +20,15 @@ + + #include "loop.h" + #include "lomount.h" ++#include "rmd160.h" ++#include "sha512.h" + #include "xstrncpy.h" + #include "nls.h" + ++#ifndef MAX ++#define MAX(a,b) ((a>b)?(a):(b)) ++#endif ++ + extern int verbose; + extern char *progname; + extern char *xstrdup (const char *s); /* not: #include "sundries.h" */ +@@ -95,12 +101,22 @@ show_loop(char *device) { + + if (loopinfo64.lo_encrypt_type || + loopinfo64.lo_crypt_name[0]) { +- char *e = 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 %d)"), +- e, loopinfo64.lo_encrypt_type); ++ printf(_(", encryption %s (type %d), 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"); + close (fd); +@@ -259,7 +275,7 @@ xgetpass(int pfd, const char *prompt) { + } + + if (pass == NULL) +- return ""; ++ return NULL; + + pass[i] = 0; + return pass; +@@ -273,12 +289,30 @@ 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, MAX(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, MAX(buflen, sizeof(tmpbuf))); ++} ++ + int + set_loop(const char *device, const char *file, unsigned long long offset, +- const char *encryption, int pfd, int *loopro) { ++ const char *encryption, const char* phash, int pfd, int *loopro, int keysz) { + struct loop_info64 loopinfo64; + int fd, ffd, mode, i; +- char *pass; ++ char *pass = NULL; + + mode = (*loopro ? O_RDONLY : O_RDWR); + if ((ffd = open(file, mode)) < 0) { +@@ -297,15 +331,39 @@ set_loop(const char *device, const char + + memset(&loopinfo64, 0, sizeof(loopinfo64)); + +- xstrncpy(loopinfo64.lo_file_name, file, LO_NAME_SIZE); ++ xstrncpy((char*)loopinfo64.lo_file_name, file, LO_NAME_SIZE); ++ ++ loopinfo64.lo_encrypt_key_size = 0; + + if (encryption && *encryption) { ++ // a hint for suse users ++ if(!strcmp(encryption, "twofishSL92")) { ++ fprintf(stderr, _("twofishSL92 is not supported via cryptoloop, please use dm-crypt to access the volume\n")); ++ return 1; ++ } + if (digits_only(encryption)) { + loopinfo64.lo_encrypt_type = atoi(encryption); + } else { +- loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI; +- snprintf(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; ++ } ++ loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI; + } + } + +@@ -325,20 +383,57 @@ set_loop(const char *device, const char + } + #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; ++ + memset(loopinfo64.lo_encrypt_key, 0, LO_KEY_SIZE); +- xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE); ++ ++ pass = xgetpass(pfd, _("Password: ")); ++ if(!pass) ++ return 1; ++ ++ // set default hash functions, loop-AES compatible ++ if(loopinfo64.lo_encrypt_type == LO_CRYPT_CRYPTOAPI) { ++ hfunc = sha512_hash_buffer; ++ if(loopinfo64.lo_encrypt_key_size == 24) hfunc = sha384_hash_buffer; ++ if(loopinfo64.lo_encrypt_key_size == 32) hfunc = sha512_hash_buffer; ++ } else { ++ hfunc = phash_none; ++ loopinfo64.lo_encrypt_key_size = keysz?keysz>>3:LO_KEY_SIZE; ++ } ++ ++ if(!loopinfo64.lo_encrypt_key_size) { ++ if(!keysz) { ++ if(verbose) ++ fprintf(stderr, _("please specify a key length\n")); ++ return 1; ++ } ++ loopinfo64.lo_encrypt_key_size = keysz>>3; ++ } ++ ++ if (phash) { ++ if(!strcasecmp(phash, "sha512")) { ++ hfunc = sha512_hash_buffer; ++ } else if(!strcasecmp(phash, "sha384")) { ++ hfunc = sha384_hash_buffer; ++ } else if(!strcasecmp(phash, "sha256")) { ++ hfunc = sha256_hash_buffer; ++ } else if(!strcasecmp(phash, "rmd160")) { ++ hfunc = phash_rmd160; ++ } else if(!strcasecmp(phash, "none")) { ++ hfunc = phash_none; ++ } else { ++ fprintf(stderr, _("unsupported hash method '%s'\n"), phash); ++ return 1; ++ } ++ } ++ ++ if(hfunc) { ++ hfunc((unsigned char*)pass, strlen(pass), loopinfo64.lo_encrypt_key, loopinfo64.lo_encrypt_key_size); ++ } ++ ++ // zero buffer + memset(pass, 0, strlen(pass)); +- loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE; + } + + if (ioctl(fd, LOOP_SET_FD, ffd) < 0) { +@@ -416,8 +511,8 @@ mutter(void) { + } + + int +-set_loop (const char *device, const char *file, unsigned long long offset, +- const char *encryption, int *loopro) { ++set_loop(const char *device, const char *file, unsigned long long offset, ++ const char *encryption, const char* phash, int pfd, int *loopro, int keysz) { + mutter(); + return 1; + } +@@ -456,7 +551,13 @@ usage(void) { + " %1$s [ options ] {-f|--find|loop_device} file # setup\n" + "\nOptions:\n" + " -e | --encryption enable data encryption with specified \n" ++ " -H | --phash hash password using specified algorithm (rmd160/sha512/sha256/sha384/none)\n" + " -h | --help this help\n" ++ " -k | --keybits 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" + " -o | --offset start at offset into file\n" + " -p | --pass-fd read passphrase from file descriptor \n" + " -r | --read-only setup read-only loop device\n" +@@ -497,11 +598,14 @@ error (const char *fmt, ...) { + int + main(int argc, char **argv) { + char *p, *offset, *encryption, *passfd, *device, *file; ++ char *keysize; ++ char *phash = NULL; + int delete, find, c, all; + int res = 0; + int showdev = 0; + int ro = 0; + int pfd = -1; ++ int keysz = 0; + unsigned long long off; + struct option longopts[] = { + { "all", 0, 0, 'a' }, +@@ -509,6 +613,8 @@ main(int argc, char **argv) { + { "encryption", 1, 0, 'e' }, + { "find", 0, 0, 'f' }, + { "help", 0, 0, 'h' }, ++ { "keybits", 1, 0, 'k' }, ++ { "phash", 1, 0, 'H' }, + { "offset", 1, 0, 'o' }, + { "pass-fd", 1, 0, 'p' }, + { "read-only", 0, 0, 'r' }, +@@ -524,12 +630,13 @@ main(int argc, char **argv) { + delete = find = all = 0; + off = 0; + offset = encryption = passfd = NULL; ++ keysize = NULL; + + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + +- while ((c = getopt_long(argc, argv, "ade:E:fho:p:rsv", ++ while ((c = getopt_long(argc, argv, "ade:E:fhk:No:p:rsvH:", + longopts, NULL)) != -1) { + switch (c) { + case 'a': +@@ -548,6 +655,12 @@ main(int argc, char **argv) { + case 'f': + find = 1; + break; ++ case 'k': ++ keysize = optarg; ++ break; ++ case 'H': ++ phash = optarg; ++ break; + case 'o': + offset = optarg; + break; +@@ -611,8 +724,10 @@ main(int argc, char **argv) { + usage(); + if (passfd && sscanf(passfd, "%d", &pfd) != 1) + usage(); ++ if (keysize && sscanf(keysize,"%d",&keysz) != 1) ++ usage(); + do { +- res = set_loop(device, file, off, encryption, pfd, &ro); ++ res = set_loop(device, file, off, encryption, phash, pfd, &ro, keysz); + if (res == 2 && find) { + if (verbose) + printf("stolen loop=%s...trying again\n", +Index: util-linux-ng-2.13rc2+git20070725/mount/mount.c +=================================================================== +--- util-linux-ng-2.13rc2+git20070725.orig/mount/mount.c ++++ util-linux-ng-2.13rc2+git20070725/mount/mount.c +@@ -93,6 +93,9 @@ static int suid = 0; + /* Contains the fd 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 */ +@@ -190,6 +193,7 @@ static int opt_nofail = 0; + + static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption, + *opt_speed, *opt_comment, *opt_uhelper; ++static const char *opt_keybits, *opt_phash, *opt_nohashpass; + + static int mounted (const char *spec0, const char *node0); + static int check_special_mountprog(const char *spec, const char *node, +@@ -204,6 +208,9 @@ static struct string_opt_map { + { "vfs=", 1, &opt_vfstype }, + { "offset=", 0, &opt_offset }, + { "encryption=", 0, &opt_encryption }, ++ { "phash=", 0, &opt_phash }, ++ { "keybits=", 0, &opt_keybits }, ++ { "nohashpass", 0, &opt_nohashpass }, + { "speed=", 0, &opt_speed }, + { "comment=", 1, &opt_comment }, + { "uhelper=", 0, &opt_uhelper }, +@@ -858,7 +865,7 @@ loop_check(const char **spec, const char + *type = opt_vfstype; + } + +- *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_encryption); ++ *loop = ((*flags & MS_LOOP) || *loopdev || opt_offset || opt_encryption || opt_phash || opt_keybits); + *loopfile = *spec; + + if (*loop) { +@@ -879,9 +886,17 @@ loop_check(const char **spec, const char + return EX_SYSERR; /* no more loop devices */ + if (verbose) + printf(_("mount: going to use the loop device %s\n"), *loopdev); +- ++ if (!keysz && opt_keybits) ++ keysz = strtoul(opt_keybits, NULL, 0); ++ if (opt_nohashpass) { ++ if(opt_phash && strcmp(opt_phash, "none")) { ++ error(_("mount: please specify either phash=%s or nohashpass\n")); ++ return EX_FAIL; ++ } ++ opt_phash = "none"; ++ } + if ((res = set_loop(*loopdev, *loopfile, offset, +- opt_encryption, pfd, &loopro))) { ++ opt_encryption, opt_phash, pfd, &loopro, keysz))) { + if (res == 2) { + /* loop dev has been grabbed by some other process, + try again, if not given explicitly */ +@@ -1184,7 +1199,7 @@ try_mount_one (const char *spec0, const + error (_("mount: %s not mounted already, or bad option"), node); + } else { + error (_("mount: wrong fs type, bad option, bad superblock on %s,\n" +- " missing codepage or other error"), ++ " missing codepage or helper program, or other error"), + spec); + + if (stat(spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) +@@ -1629,6 +1644,7 @@ static struct option longopts[] = { + { "options", 1, 0, 'o' }, + { "test-opts", 1, 0, 'O' }, + { "pass-fd", 1, 0, 'p' }, ++ { "keybits", 1, 0, 'k' }, + { "types", 1, 0, 't' }, + { "bind", 0, 0, 128 }, + { "replace", 0, 0, 129 }, +@@ -1781,6 +1797,7 @@ main(int argc, char *argv[]) { + char *options = NULL, *test_opts = NULL, *node; + const char *spec = NULL; + char *label = NULL; ++ char *keysize = NULL; + char *uuid = NULL; + char *types = NULL; + char *p; +@@ -1811,7 +1828,7 @@ main(int argc, char *argv[]) { + initproctitle(argc, argv); + #endif + +- while ((c = getopt_long (argc, argv, "afFhilL:no:O:p:rsU:vVwt:", ++ while ((c = getopt_long (argc, argv, "afFhik:lL:no:O:p:rsU:vVwt:", + longopts, NULL)) != -1) { + switch (c) { + case 'a': /* mount everything in fstab */ +@@ -1829,6 +1846,9 @@ main(int argc, char *argv[]) { + case 'i': + external_allowed = 0; + break; ++ case 'k': ++ keysize = optarg; ++ break; + case 'l': + list_with_volumelabel = 1; + break; +@@ -1975,6 +1995,9 @@ main(int argc, char *argv[]) { + create_mtab (); + } + ++ 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: + /* mount -a */ +Index: util-linux-ng-2.13rc2+git20070725/mount/lomount.h +=================================================================== +--- util-linux-ng-2.13rc2+git20070725.orig/mount/lomount.h ++++ util-linux-ng-2.13rc2+git20070725/mount/lomount.h +@@ -1,6 +1,6 @@ + extern int verbose; +-extern int set_loop(const char *, const char *, unsigned long long, +- const char *, int, int *); ++extern int set_loop(const char *device, const char *file, unsigned long long offset, ++ const char *encryption, const char* phash, int pfd, int *loopro, int keysz); + extern int del_loop(const char *); + extern int is_loop_device(const char *); + extern char * find_unused_loop_device(void); +Index: util-linux-ng-2.13rc2+git20070725/mount/rmd160.c +=================================================================== +--- /dev/null ++++ util-linux-ng-2.13rc2+git20070725/mount/rmd160.c +@@ -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 . 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 /* (mm) for memcpy */ ++#include /* (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, const 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, const 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( unsigned char *outbuf, const unsigned char *buffer, size_t length ) ++{ ++ RMD160_CONTEXT hd; ++ ++ rmd160_init( &hd ); ++ rmd160_write( &hd, buffer, length ); ++ rmd160_final( &hd ); ++ memcpy( outbuf, hd.buf, 20 ); ++} +Index: util-linux-ng-2.13rc2+git20070725/mount/sha512.c +=================================================================== +--- /dev/null ++++ util-linux-ng-2.13rc2+git20070725/mount/sha512.c +@@ -0,0 +1,432 @@ ++/* ++ * sha512.c ++ * ++ * Written by Jari Ruusu, April 16 2001 ++ * ++ * Copyright 2001 by Jari Ruusu. ++ * Redistribution of this file is permitted under the GNU Public License. ++ */ ++ ++#include ++#include ++#include "sha512.h" ++ ++/* Define one or more of these. If none is defined, you get all of them */ ++#if !defined(SHA256_NEEDED)&&!defined(SHA512_NEEDED)&&!defined(SHA384_NEEDED) ++# define SHA256_NEEDED 1 ++# define SHA512_NEEDED 1 ++# define SHA384_NEEDED 1 ++#endif ++ ++#if defined(SHA256_NEEDED) ++static const u_int32_t sha256_hashInit[8] = { ++ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, ++ 0x1f83d9ab, 0x5be0cd19 ++}; ++static const u_int32_t sha256_K[64] = { ++ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, ++ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, ++ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, ++ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, ++ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, ++ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, ++ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, ++ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, ++ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, ++ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, ++ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ++}; ++#endif ++ ++#if defined(SHA512_NEEDED) ++static const u_int64_t sha512_hashInit[8] = { ++ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, ++ 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, ++ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL ++}; ++#endif ++ ++#if defined(SHA384_NEEDED) ++static const u_int64_t sha384_hashInit[8] = { ++ 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, 0x9159015a3070dd17ULL, ++ 0x152fecd8f70e5939ULL, 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, ++ 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL ++}; ++#endif ++ ++#if defined(SHA512_NEEDED) || defined(SHA384_NEEDED) ++static const u_int64_t sha512_K[80] = { ++ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, ++ 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, ++ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, ++ 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, ++ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, ++ 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, ++ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, ++ 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, ++ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, ++ 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, ++ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, ++ 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, ++ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, ++ 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, ++ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, ++ 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, ++ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, ++ 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, ++ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, ++ 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, ++ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, ++ 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, ++ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, ++ 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, ++ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, ++ 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, ++ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL ++}; ++#endif ++ ++#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) ++#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) ++#define R(x,y) ((y) >> (x)) ++ ++#if defined(SHA256_NEEDED) ++void sha256_init(sha256_context *ctx) ++{ ++ memcpy(&ctx->sha_H[0], &sha256_hashInit[0], sizeof(ctx->sha_H)); ++ ctx->sha_blocks = 0; ++ ctx->sha_bufCnt = 0; ++} ++ ++#define S(x,y) (((y) >> (x)) | ((y) << (32 - (x)))) ++#define uSig0(x) ((S(2,(x))) ^ (S(13,(x))) ^ (S(22,(x)))) ++#define uSig1(x) ((S(6,(x))) ^ (S(11,(x))) ^ (S(25,(x)))) ++#define lSig0(x) ((S(7,(x))) ^ (S(18,(x))) ^ (R(3,(x)))) ++#define lSig1(x) ((S(17,(x))) ^ (S(19,(x))) ^ (R(10,(x)))) ++ ++static void sha256_transform(sha256_context *ctx, const unsigned char *datap) ++{ ++ register int j; ++ u_int32_t a, b, c, d, e, f, g, h; ++ u_int32_t T1, T2, W[64], Wm2, Wm15; ++ ++ /* read the data, big endian byte order */ ++ j = 0; ++ do { ++ W[j] = (((u_int32_t)(datap[0]))<<24) | (((u_int32_t)(datap[1]))<<16) | ++ (((u_int32_t)(datap[2]))<<8 ) | ((u_int32_t)(datap[3])); ++ datap += 4; ++ } while(++j < 16); ++ ++ /* initialize variables a...h */ ++ a = ctx->sha_H[0]; ++ b = ctx->sha_H[1]; ++ c = ctx->sha_H[2]; ++ d = ctx->sha_H[3]; ++ e = ctx->sha_H[4]; ++ f = ctx->sha_H[5]; ++ g = ctx->sha_H[6]; ++ h = ctx->sha_H[7]; ++ ++ /* apply compression function */ ++ j = 0; ++ do { ++ if(j >= 16) { ++ Wm2 = W[j - 2]; ++ Wm15 = W[j - 15]; ++ W[j] = lSig1(Wm2) + W[j - 7] + lSig0(Wm15) + W[j - 16]; ++ } ++ T1 = h + uSig1(e) + Ch(e,f,g) + sha256_K[j] + W[j]; ++ T2 = uSig0(a) + Maj(a,b,c); ++ h = g; g = f; f = e; ++ e = d + T1; ++ d = c; c = b; b = a; ++ a = T1 + T2; ++ } while(++j < 64); ++ ++ /* compute intermediate hash value */ ++ ctx->sha_H[0] += a; ++ ctx->sha_H[1] += b; ++ ctx->sha_H[2] += c; ++ ctx->sha_H[3] += d; ++ ctx->sha_H[4] += e; ++ ctx->sha_H[5] += f; ++ ctx->sha_H[6] += g; ++ ctx->sha_H[7] += h; ++ ++ ctx->sha_blocks++; ++} ++ ++void sha256_write(sha256_context *ctx, const unsigned char *datap, int length) ++{ ++ while(length > 0) { ++ if(!ctx->sha_bufCnt) { ++ while(length >= sizeof(ctx->sha_out)) { ++ sha256_transform(ctx, datap); ++ datap += sizeof(ctx->sha_out); ++ length -= sizeof(ctx->sha_out); ++ } ++ if(!length) return; ++ } ++ ctx->sha_out[ctx->sha_bufCnt] = *datap++; ++ length--; ++ if(++ctx->sha_bufCnt == sizeof(ctx->sha_out)) { ++ sha256_transform(ctx, &ctx->sha_out[0]); ++ ctx->sha_bufCnt = 0; ++ } ++ } ++} ++ ++void sha256_final(sha256_context *ctx) ++{ ++ register int j; ++ u_int64_t bitLength; ++ u_int32_t i; ++ unsigned char padByte, *datap; ++ ++ bitLength = (ctx->sha_blocks << 9) | (ctx->sha_bufCnt << 3); ++ padByte = 0x80; ++ sha256_write(ctx, &padByte, 1); ++ ++ /* pad extra space with zeroes */ ++ padByte = 0; ++ while(ctx->sha_bufCnt != 56) { ++ sha256_write(ctx, &padByte, 1); ++ } ++ ++ /* write bit length, big endian byte order */ ++ ctx->sha_out[56] = bitLength >> 56; ++ ctx->sha_out[57] = bitLength >> 48; ++ ctx->sha_out[58] = bitLength >> 40; ++ ctx->sha_out[59] = bitLength >> 32; ++ ctx->sha_out[60] = bitLength >> 24; ++ ctx->sha_out[61] = bitLength >> 16; ++ ctx->sha_out[62] = bitLength >> 8; ++ ctx->sha_out[63] = bitLength; ++ sha256_transform(ctx, &ctx->sha_out[0]); ++ ++ /* return results in ctx->sha_out[0...31] */ ++ datap = &ctx->sha_out[0]; ++ j = 0; ++ do { ++ i = ctx->sha_H[j]; ++ datap[0] = i >> 24; ++ datap[1] = i >> 16; ++ datap[2] = i >> 8; ++ datap[3] = i; ++ datap += 4; ++ } while(++j < 8); ++ ++ /* clear sensitive information */ ++ memset(&ctx->sha_out[32], 0, sizeof(sha256_context) - 32); ++} ++ ++void sha256_hash_buffer(const unsigned char *ib, size_t ile, unsigned char *ob, size_t ole) ++{ ++ sha256_context ctx; ++ ++ if(ole < 1) return; ++ memset(ob, 0, ole); ++ if(ole > 32) ole = 32; ++ sha256_init(&ctx); ++ sha256_write(&ctx, ib, ile); ++ sha256_final(&ctx); ++ memcpy(ob, &ctx.sha_out[0], ole); ++ memset(&ctx, 0, sizeof(ctx)); ++} ++ ++#endif ++ ++#if defined(SHA512_NEEDED) ++void sha512_init(sha512_context *ctx) ++{ ++ memcpy(&ctx->sha_H[0], &sha512_hashInit[0], sizeof(ctx->sha_H)); ++ ctx->sha_blocks = 0; ++ ctx->sha_blocksMSB = 0; ++ ctx->sha_bufCnt = 0; ++} ++#endif ++ ++#if defined(SHA512_NEEDED) || defined(SHA384_NEEDED) ++#undef S ++#undef uSig0 ++#undef uSig1 ++#undef lSig0 ++#undef lSig1 ++#define S(x,y) (((y) >> (x)) | ((y) << (64 - (x)))) ++#define uSig0(x) ((S(28,(x))) ^ (S(34,(x))) ^ (S(39,(x)))) ++#define uSig1(x) ((S(14,(x))) ^ (S(18,(x))) ^ (S(41,(x)))) ++#define lSig0(x) ((S(1,(x))) ^ (S(8,(x))) ^ (R(7,(x)))) ++#define lSig1(x) ((S(19,(x))) ^ (S(61,(x))) ^ (R(6,(x)))) ++ ++static void sha512_transform(sha512_context *ctx, const unsigned char *datap) ++{ ++ register int j; ++ u_int64_t a, b, c, d, e, f, g, h; ++ u_int64_t T1, T2, W[80], Wm2, Wm15; ++ ++ /* read the data, big endian byte order */ ++ j = 0; ++ do { ++ W[j] = (((u_int64_t)(datap[0]))<<56) | (((u_int64_t)(datap[1]))<<48) | ++ (((u_int64_t)(datap[2]))<<40) | (((u_int64_t)(datap[3]))<<32) | ++ (((u_int64_t)(datap[4]))<<24) | (((u_int64_t)(datap[5]))<<16) | ++ (((u_int64_t)(datap[6]))<<8 ) | ((u_int64_t)(datap[7])); ++ datap += 8; ++ } while(++j < 16); ++ ++ /* initialize variables a...h */ ++ a = ctx->sha_H[0]; ++ b = ctx->sha_H[1]; ++ c = ctx->sha_H[2]; ++ d = ctx->sha_H[3]; ++ e = ctx->sha_H[4]; ++ f = ctx->sha_H[5]; ++ g = ctx->sha_H[6]; ++ h = ctx->sha_H[7]; ++ ++ /* apply compression function */ ++ j = 0; ++ do { ++ if(j >= 16) { ++ Wm2 = W[j - 2]; ++ Wm15 = W[j - 15]; ++ W[j] = lSig1(Wm2) + W[j - 7] + lSig0(Wm15) + W[j - 16]; ++ } ++ T1 = h + uSig1(e) + Ch(e,f,g) + sha512_K[j] + W[j]; ++ T2 = uSig0(a) + Maj(a,b,c); ++ h = g; g = f; f = e; ++ e = d + T1; ++ d = c; c = b; b = a; ++ a = T1 + T2; ++ } while(++j < 80); ++ ++ /* compute intermediate hash value */ ++ ctx->sha_H[0] += a; ++ ctx->sha_H[1] += b; ++ ctx->sha_H[2] += c; ++ ctx->sha_H[3] += d; ++ ctx->sha_H[4] += e; ++ ctx->sha_H[5] += f; ++ ctx->sha_H[6] += g; ++ ctx->sha_H[7] += h; ++ ++ ctx->sha_blocks++; ++ if(!ctx->sha_blocks) ctx->sha_blocksMSB++; ++} ++ ++void sha512_write(sha512_context *ctx, const unsigned char *datap, int length) ++{ ++ while(length > 0) { ++ if(!ctx->sha_bufCnt) { ++ while(length >= sizeof(ctx->sha_out)) { ++ sha512_transform(ctx, datap); ++ datap += sizeof(ctx->sha_out); ++ length -= sizeof(ctx->sha_out); ++ } ++ if(!length) return; ++ } ++ ctx->sha_out[ctx->sha_bufCnt] = *datap++; ++ length--; ++ if(++ctx->sha_bufCnt == sizeof(ctx->sha_out)) { ++ sha512_transform(ctx, &ctx->sha_out[0]); ++ ctx->sha_bufCnt = 0; ++ } ++ } ++} ++ ++void sha512_final(sha512_context *ctx) ++{ ++ register int j; ++ u_int64_t bitLength, bitLengthMSB; ++ u_int64_t i; ++ unsigned char padByte, *datap; ++ ++ bitLength = (ctx->sha_blocks << 10) | (ctx->sha_bufCnt << 3); ++ bitLengthMSB = (ctx->sha_blocksMSB << 10) | (ctx->sha_blocks >> 54); ++ padByte = 0x80; ++ sha512_write(ctx, &padByte, 1); ++ ++ /* pad extra space with zeroes */ ++ padByte = 0; ++ while(ctx->sha_bufCnt != 112) { ++ sha512_write(ctx, &padByte, 1); ++ } ++ ++ /* write bit length, big endian byte order */ ++ ctx->sha_out[112] = bitLengthMSB >> 56; ++ ctx->sha_out[113] = bitLengthMSB >> 48; ++ ctx->sha_out[114] = bitLengthMSB >> 40; ++ ctx->sha_out[115] = bitLengthMSB >> 32; ++ ctx->sha_out[116] = bitLengthMSB >> 24; ++ ctx->sha_out[117] = bitLengthMSB >> 16; ++ ctx->sha_out[118] = bitLengthMSB >> 8; ++ ctx->sha_out[119] = bitLengthMSB; ++ ctx->sha_out[120] = bitLength >> 56; ++ ctx->sha_out[121] = bitLength >> 48; ++ ctx->sha_out[122] = bitLength >> 40; ++ ctx->sha_out[123] = bitLength >> 32; ++ ctx->sha_out[124] = bitLength >> 24; ++ ctx->sha_out[125] = bitLength >> 16; ++ ctx->sha_out[126] = bitLength >> 8; ++ ctx->sha_out[127] = bitLength; ++ sha512_transform(ctx, &ctx->sha_out[0]); ++ ++ /* return results in ctx->sha_out[0...63] */ ++ datap = &ctx->sha_out[0]; ++ j = 0; ++ do { ++ i = ctx->sha_H[j]; ++ datap[0] = i >> 56; ++ datap[1] = i >> 48; ++ datap[2] = i >> 40; ++ datap[3] = i >> 32; ++ datap[4] = i >> 24; ++ datap[5] = i >> 16; ++ datap[6] = i >> 8; ++ datap[7] = i; ++ datap += 8; ++ } while(++j < 8); ++ ++ /* clear sensitive information */ ++ memset(&ctx->sha_out[64], 0, sizeof(sha512_context) - 64); ++} ++ ++void sha512_hash_buffer(const unsigned char *ib, size_t ile, unsigned char *ob, size_t ole) ++{ ++ sha512_context ctx; ++ ++ if(ole < 1) return; ++ memset(ob, 0, ole); ++ if(ole > 64) ole = 64; ++ sha512_init(&ctx); ++ sha512_write(&ctx, ib, ile); ++ sha512_final(&ctx); ++ memcpy(ob, &ctx.sha_out[0], ole); ++ memset(&ctx, 0, sizeof(ctx)); ++} ++#endif ++ ++#if defined(SHA384_NEEDED) ++void sha384_init(sha512_context *ctx) ++{ ++ memcpy(&ctx->sha_H[0], &sha384_hashInit[0], sizeof(ctx->sha_H)); ++ ctx->sha_blocks = 0; ++ ctx->sha_blocksMSB = 0; ++ ctx->sha_bufCnt = 0; ++} ++ ++void sha384_hash_buffer(const unsigned char *ib, size_t ile, unsigned char *ob, size_t ole) ++{ ++ sha512_context ctx; ++ ++ if(ole < 1) return; ++ memset(ob, 0, ole); ++ if(ole > 48) ole = 48; ++ sha384_init(&ctx); ++ sha512_write(&ctx, ib, ile); ++ sha512_final(&ctx); ++ memcpy(ob, &ctx.sha_out[0], ole); ++ memset(&ctx, 0, sizeof(ctx)); ++} ++#endif +Index: util-linux-ng-2.13rc2+git20070725/mount/sha512.h +=================================================================== +--- /dev/null ++++ util-linux-ng-2.13rc2+git20070725/mount/sha512.h +@@ -0,0 +1,45 @@ ++/* ++ * sha512.h ++ * ++ * Written by Jari Ruusu, April 16 2001 ++ * ++ * Copyright 2001 by Jari Ruusu. ++ * Redistribution of this file is permitted under the GNU Public License. ++ */ ++ ++#include ++ ++typedef struct { ++ unsigned char sha_out[64]; /* results are here, bytes 0...31 */ ++ u_int32_t sha_H[8]; ++ u_int64_t sha_blocks; ++ int sha_bufCnt; ++} sha256_context; ++ ++typedef struct { ++ unsigned char sha_out[128]; /* results are here, bytes 0...63 */ ++ u_int64_t sha_H[8]; ++ u_int64_t sha_blocks; ++ u_int64_t sha_blocksMSB; ++ int sha_bufCnt; ++} sha512_context; ++ ++/* no sha384_context, use sha512_context */ ++ ++/* 256 bit hash, provides 128 bits of security against collision attacks */ ++extern void sha256_init(sha256_context *); ++extern void sha256_write(sha256_context *, const unsigned char *, int); ++extern void sha256_final(sha256_context *); ++extern void sha256_hash_buffer(const unsigned char *, size_t, unsigned char *, size_t); ++ ++/* 512 bit hash, provides 256 bits of security against collision attacks */ ++extern void sha512_init(sha512_context *); ++extern void sha512_write(sha512_context *, const unsigned char *, int); ++extern void sha512_final(sha512_context *); ++extern void sha512_hash_buffer(const unsigned char *, size_t, unsigned char *, size_t); ++ ++/* 384 bit hash, provides 192 bits of security against collision attacks */ ++extern void sha384_init(sha512_context *); ++/* no sha384_write(), use sha512_write() */ ++/* no sha384_final(), use sha512_final(), result in ctx->sha_out[0...47] */ ++extern void sha384_hash_buffer(const unsigned char *, size_t, unsigned char *, size_t); diff --git a/util-linux.changes b/util-linux.changes index 6e9c3cf..c2867ee 100644 --- a/util-linux.changes +++ b/util-linux.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Aug 28 16:42:04 CEST 2007 - lnussel@suse.de + +- add support for specifying the key length and password hash + algorithm [#304861] + ------------------------------------------------------------------- Fri Aug 24 14:09:19 CEST 2007 - mkoenig@suse.de diff --git a/util-linux.spec b/util-linux.spec index 9c30509..9c5485b 100644 --- a/util-linux.spec +++ b/util-linux.spec @@ -21,7 +21,7 @@ License: BSD 3-Clause, GPL v2 or later Group: System/Base Autoreqprov: on Version: 2.12r+2.13rc2+git20070725 -Release: 12 +Release: 14 %define upver 2.13rc2+git20070725 Summary: A collection of basic system utilities Source: ftp://ftp.kernel.org/pub/linux/utils/util-linux/%name-ng-%upver.tar.bz2 @@ -71,6 +71,9 @@ Patch45: util-linux-2.13-sys_utils_build_rdev_x86_64.patch Patch46: util-linux-2.13-loop.patch Patch47: util-linux-2.13-mount_create_mtab.patch Patch48: util-linux-2.13-schedutils_error_handling.patch +# 304861 - support password hashing and key length +Patch49: cryptsetup-2.13-crypto.diff +## ## ## adjtimex ## @@ -117,6 +120,7 @@ Authors: %patch46 -p1 %patch47 -p1 %patch48 -p1 +%patch49 -p1 # cd adjtimex-* %patch50 -p1 @@ -557,6 +561,9 @@ fi #%endif %changelog +* Tue Aug 28 2007 - lnussel@suse.de +- add support for specifying the key length and password hash + algorithm [#304861] * Fri Aug 24 2007 - mkoenig@suse.de - avoid duplicates of root fs if defined with LABEL in fstab [#297959]