From da95c7c14b2e63310a0a9ac0c594d6e2d903c072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 4 May 2005 13:00:00 +0000 Subject: [PATCH] added rmd160 checksum tool from http://www.nic.com/~cheah/rmd160.tar.gz git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12570 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/bin/Jamfile | 1 + src/bin/rmd160/Jamfile | 6 + src/bin/rmd160/main.c | 424 ++++++++++++++++++++++++++++++++++++++++ src/bin/rmd160/rmd160.1 | 62 ++++++ src/bin/rmd160/rmd160.c | 285 +++++++++++++++++++++++++++ src/bin/rmd160/rmd160.h | 98 ++++++++++ 6 files changed, 876 insertions(+) create mode 100644 src/bin/rmd160/Jamfile create mode 100644 src/bin/rmd160/main.c create mode 100644 src/bin/rmd160/rmd160.1 create mode 100644 src/bin/rmd160/rmd160.c create mode 100644 src/bin/rmd160/rmd160.h diff --git a/src/bin/Jamfile b/src/bin/Jamfile index 563634f7f0..ef177f27d9 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -125,6 +125,7 @@ SubInclude OBOS_TOP src bin makeudfimage ; SubInclude OBOS_TOP src bin mkdos ; SubInclude OBOS_TOP src bin patch ; SubInclude OBOS_TOP src bin pc ; +SubInclude OBOS_TOP src bin rmd160 ; SubInclude OBOS_TOP src bin sed ; SubInclude OBOS_TOP src bin sharutils ; SubInclude OBOS_TOP src bin strace ; diff --git a/src/bin/rmd160/Jamfile b/src/bin/rmd160/Jamfile new file mode 100644 index 0000000000..6265239cd6 --- /dev/null +++ b/src/bin/rmd160/Jamfile @@ -0,0 +1,6 @@ +SubDir OBOS_TOP src bin rmd160 ; + +BinCommand rmd160 : + rmd160.c + main.c +; diff --git a/src/bin/rmd160/main.c b/src/bin/rmd160/main.c new file mode 100644 index 0000000000..e65ebf2a0e --- /dev/null +++ b/src/bin/rmd160/main.c @@ -0,0 +1,424 @@ +/* + rmd.c + RIPEMD-160 generate and check utility + by Po Shan Cheah, Copyright (c) 1997 + You may distribute this program freely provided this notice + is retained. + + January 5, 1997: + Initial release. + +*/ + +#include "rmd160.h" +#include +#include +#include +#include +#include +#include + +#define BUFLEN 4096 +#define RMDBITS 160 + +int binary_mode = 0; +int verbose_mode = 0; +char *progname = ""; + +int prog_rc = 0; + +void setrc(int newrc) { + + /* raises but never lowers the program return code to newrc */ + + if (newrc > prog_rc) + prog_rc = newrc; +} + +int cvthex(char c) { + /* convert a hex digit to an integer */ + + c = toupper(c); + + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return c - '0'; +} + +int hexdigit(char c) { + /* returns true if character is a hexadecimal digit */ + + return + (c >= '0' && c <= '9') || + (toupper(c) >= 'A' && toupper(c) <= 'F'); +} + +#define ESCAPE '%' + +char *encodestr(char *instr) { + /* replace unprintable characters and % itself with %HH */ + + static char buf[BUFLEN]; + char *outstr = buf; + + for ( ; *instr; ++instr) { + if (isprint(*instr) && !isspace(*instr) && *instr != ESCAPE) + *outstr++ = *instr; + else { + sprintf(outstr, "%%%02x", *instr); + outstr += 3; + } + } + *outstr = '\0'; + return buf; +} + +char *decodestr(char *instr) { + /* undo what encodestr did */ + + static char buf[BUFLEN]; + char *outstr = buf; + + while (*instr) { + if (*instr == ESCAPE && + hexdigit(instr[1]) && + hexdigit(instr[2])) { + *outstr++ = cvthex(instr[1]) << 4 | cvthex(instr[2]); + instr += 3; + } + else + *outstr++ = *instr ++; + } + *outstr = '\0'; + return buf; +} + +void pack_chunk(word *chunk, byte *buf) { + /* pack 64 bytes into 16 little-endian 32-bit words */ + + int j; + + for (j = 0; j < 16; ++j, buf += 4) + *chunk++ = (word) buf[0] | (word) buf[1] << 8 | + (word) buf[2] << 16 | (word) buf[3] << 24 ; +} + +byte *rmdfp(char *fname, FILE *fp) { + /* calculate the message digest of a file + and return it in string form */ + + int bytesread; + int i; + word tmp; + word chunk[16]; + char buf[BUFLEN]; + word length[2]; + word mdbuf[RMDBITS / 32]; + static byte code[RMDBITS / 8]; + + length[0] = length[1] = 0; + MDinit(mdbuf); + + /* do all full BUFLEN portions */ + + while ((bytesread = fread(buf, 1, BUFLEN, fp)) == BUFLEN) { + + for (i = 0; i < BUFLEN; i += 64) { + pack_chunk(chunk, buf + i); + MDcompress(mdbuf, chunk); + } + + if ((tmp = length[0] + bytesread) < length[0]) + ++ length[1]; /* overflow */ + length[0] = tmp; + } + + if (ferror(fp)) { + fprintf(stderr, "%s: %s\n", fname, strerror(errno)); + setrc(2); + return NULL; + } + + /* do all the remaining 64-byte blocks */ + + for (i = 0; i < bytesread - 63; i += 64) { + pack_chunk(chunk, buf + i); + MDcompress(mdbuf, chunk); + } + + if ((tmp = length[0] + bytesread) < length[0]) + ++ length[1]; /* overflow */ + length[0] = tmp; + + /* do the last partial or zero length block */ + + MDfinish(mdbuf, buf + i, length[0] << 3, + length[0] >> 29 | length[1] << 3); + + /* convert to 64-byte string using little-endian conversion */ + + for (i = 0; i < RMDBITS / 8; i += 4) { + + word wd = mdbuf[i >> 2]; + + code[i] = (byte) (wd); + code[i + 1] = (byte) (wd >> 8); + code[i + 2] = (byte) (wd >> 16); + code[i + 3] = (byte) (wd >> 24); + } + + return code; +} + +void printcode(byte *code) { + /* print a RIPEMD-160 code */ + + int i; + + for (i = 0; i < RMDBITS / 8; ++i) + printf("%02x", code[i]); +} + +byte *rmdfile(char *fname) { + /* calculate the message digest of a single file + and output the digest followed by the file name */ + + FILE *fp; + + fp = fopen(fname, binary_mode ? "rb" : "r"); + if (fp == NULL) { + fprintf(stderr, "%s: %s\n", fname, strerror(errno)); + setrc(2); + return NULL; + } + + else { + byte *code = rmdfp(fname, fp); + fclose(fp); + return code; + } +} + +int checkdigest(char *digest) { + /* returns true if string is a valid message digest string */ + + if (strlen(digest) != RMDBITS / 8 * 2) + return 0; + + for ( ; *digest; ++digest) { + if ( ! hexdigit(*digest)) + return 0; + } + + return 1; +} + +void stringtocode(byte *code, char *str) { + /* convert message digest string into 20 byte code */ + + int i; + + for (i = 0; i < RMDBITS / 8; ++i, str += 2) + *code++ = cvthex(str[0]) << 4 | cvthex(str[1]); +} + +void checkfp(char *fname, FILE *fp) { + /* check message digests. message digest data comes from + the given open file handle. */ + + int lineno = 0; + int nfail = 0; + int nfile = 0; + char *filename; + byte *code; + byte inputcode[RMDBITS / 8]; + char line[BUFLEN]; + char digest[BUFLEN]; + char infilename[BUFLEN]; + + while (fgets(line, BUFLEN, fp)) { + + ++lineno; + + /* error checking */ + + if (sscanf(line, "%s%s", digest, infilename) < 2) { + fprintf(stderr, "%s: invalid input on line %d\n", + progname, lineno); + setrc(2); + continue; + } + + if (!checkdigest(digest)) { + fprintf(stderr, "%s: invalid message digest on line %d\n", + progname, lineno); + setrc(2); + continue; + } + + stringtocode(inputcode, digest); + + /* calculate message digest for file */ + + filename = decodestr(infilename); + + code = rmdfile(filename); + if (code) { + + ++nfile; + + /* compare digests */ + + if (memcmp(inputcode, code, RMDBITS / 8) != 0) { + ++nfail; + setrc(1); + + if (verbose_mode) + printf("FAILED %s\n", filename); + else + printf("%s: RIPEMD-160 check failed for `%s'\n", + progname, filename); + } + + else { + if (verbose_mode) + printf("GOOD %s\n", filename); + } + } + } + + if (verbose_mode && nfail) + printf("%s: %d of %d file(s) failed RIPEMD-160 check\n", + progname, nfail, nfile); + + if (ferror(fp)) { + fprintf(stderr, "%s: %s\n", fname, strerror(errno)); + setrc(2); + } +} + +void checkfile(char *fname) { + /* check message digests. message digest data comes from + the named file. */ + + FILE *fp; + + fp = fopen(fname, "r"); + if (fp == NULL) { + fprintf(stderr, "%s: %s\n", fname, strerror(errno)); + setrc(2); + } + + else { + checkfp(fname, fp); + fclose(fp); + } +} + +int main(int argc, char *argv[]) { + + int c; + int check_mode = 0; + + progname = argv[0]; + + /* parse command line arguments */ + + while ((c = getopt(argc, argv, "bcvh")) >= 0) { + + switch (c) { + + case 'b': + binary_mode = 1; + break; + + case 'c': + check_mode = 1; + break; + + case 'v': + verbose_mode = 1; + break; + + case 'h': + case ':': + case '?': + printf("Usage: %s [-b] [-c] [-v] [...]\n" + "Generates or checks RIPEMD-160 message digests\n" + " -b read files in binary mode\n" + " -c check message digests\n" + " -v verbose, print file names while checking\n\n" + "If -c is not specified, then one message digest is " + "generated per file\n" + "and sent to standard output. If no files are specified " + "then input is\n" + "taken from standard input and only one message digest " + "will be\n" + "generated.\n\n" + "If -c is specified then message digests for a list of " + "files are\n" + "checked. The input should be a table in the same format " + "as the output\n" + "of this program when message digests are generated. If a " + "file is\n" + "specified then the message digest table is read from that " + "file. If no\n" + "file is specified, then the message digest table is read " + "from standard\n" + "input.\n", progname); + exit(0); + } + } + + if (check_mode) { + + if (optind < argc) { + + /* check using data from file named on command line */ + + checkfile(argv[optind]); + + } + + else { + + /* check using data from standard input */ + + checkfp("(stdin)", stdin); + + } + } + + else { + + if (optind < argc) { + + /* process file arguments */ + + for ( ; optind < argc; ++optind) { + + byte *code = rmdfile(argv[optind]); + + if (code) { + printcode(code); + printf(" %s\n", encodestr(argv[optind])); + } + } + } + + else { + + /* no file arguments so take input from stdin */ + + byte *code = rmdfp("(stdin)", stdin); + + if (code) { + printcode(code); + printf("\n"); + } + } + } + + return prog_rc; +} diff --git a/src/bin/rmd160/rmd160.1 b/src/bin/rmd160/rmd160.1 new file mode 100644 index 0000000000..94c970366b --- /dev/null +++ b/src/bin/rmd160/rmd160.1 @@ -0,0 +1,62 @@ +.TH rmd160 1 "4 January 1997" "Linux" "Linux Programmer's Manual" +.SH NAME +rmd160 \- generate and check RIPEMD-160 message digests +.SH SYNOPSIS +.BR "rmd160 " [ +.IR file " ] ..." +.br +.BR "rmd160 " [ " \-bv " ] " \-c " [ +.I file +.RB ] +.SH DESCRIPTION +\fBrmd160\fP generates and checks RIPEMD-160 message digests. These +message digests are 160-bit signatures of the input files. \fBrmd160\fP +can be used to verify the integrity of binaries posted to usenet +newsgroups or files made available for distribution via anonymous ftp. +.PP +Message digests for a tree of files can be generated with +a command similar to the following: +.PP + find . -type f -print | xargs md5sum +.PP +The output of this command is suitable as input for the \fB-c\fP +option. + +.SH OPTIONS +.TP +.B \-c +Check message digests. Input is taken from standard input or from the +first file specified on the command line. The input should be in the +same format as the message digest output generated by \fBrmd160\fP +when this option is not specified. +.TP +.B \-v +Verbose. Print all file names when checking and the result of each +message digest check. If this option is not specified then only files +that failed the check will be printed. +.TP +.B \-b +Read files in binary mode. This option has no effect on Unix systems. +.SH RETURN VALUES +Status codes returned by \fBrmd160\fP: +.TP +.B 2 +fatal or I/O related errors +.TP +.B 1 +one or more files failed the message digest check +.TP +.B 0 +no errors and all files passed the message digest check +.SH CREDITS +The \fBrmd160\fP program was written by Po Shan Cheah and may be +freely distributed provided all authorship and copyright notices are +retained. The interface for \fBrmd160\fP is based on \fBmd5sum\fP by +Branko Lankester. +.PP +The underlying implementation of RIPEMD-160 was written by +Antoon Bosselaers of Katholieke Universiteit Leuven and is available +in Dr. Dobb's Journal (January 1997). +.SH SEE ALSO +.BR "sum" "(1), " "cksum" "(1), " +.BR "pgp" "(1), " "md5sum" "(1)" \ No newline at end of file diff --git a/src/bin/rmd160/rmd160.c b/src/bin/rmd160/rmd160.c new file mode 100644 index 0000000000..defe5565a9 --- /dev/null +++ b/src/bin/rmd160/rmd160.c @@ -0,0 +1,285 @@ +/********************************************************************\ + * FILE: rmd160.c + * CONTENTS: A sample C-implementation of the RIPEMD-160 hash-function. + * TARGET: any computer with an ANSI C compiler + * AUTHOR: Antoon Bosselaers, Dept. Electrical Eng.-ESAT/COSIC + * DATE: 1 March 1996 VERSION: 1.0 + ********************************************************************** + * Copyright (c) Katholieke Universiteit Leuven 1996, All Rights Reserved + * The Katholieke Universiteit Leuven makes no representations concerning + * either the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" without + * express or implied warranty of any kind. These notices must be retained + * in any copies of any part of this documentation and/or software. +\********************************************************************/ + +/* header files */ +#include +#include +#include +#include "rmd160.h" + +/********************************************************************/ +void MDinit(word *MDbuf) +/* Initialization of the 5-word MDbuf array to the magic + initialization constants + */ +{ + MDbuf[0] = 0x67452301UL; + MDbuf[1] = 0xefcdab89UL; + MDbuf[2] = 0x98badcfeUL; + MDbuf[3] = 0x10325476UL; + MDbuf[4] = 0xc3d2e1f0UL; +} + +/********************************************************************/ +void MDcompress(word *MDbuf, word *X) +/* The compression function is called for every complete 64-byte + message block. The 5-word internal state MDbuf is updated using + message words X[0] through X[15]. The conversion from a string + of 64 bytes to an array of 16 words using a Little-endian + convention is the responsibility of the calling function. +*/ +{ + /* make two copies of the old state */ + word aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], + dd = MDbuf[3], ee = MDbuf[4]; + word aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], + ddd = MDbuf[3], eee = MDbuf[4]; + + /* round 1 */ + FF1(aa, bb, cc, dd, ee, X[ 0], 11); + FF1(ee, aa, bb, cc, dd, X[ 1], 14); + FF1(dd, ee, aa, bb, cc, X[ 2], 15); + FF1(cc, dd, ee, aa, bb, X[ 3], 12); + FF1(bb, cc, dd, ee, aa, X[ 4], 5); + FF1(aa, bb, cc, dd, ee, X[ 5], 8); + FF1(ee, aa, bb, cc, dd, X[ 6], 7); + FF1(dd, ee, aa, bb, cc, X[ 7], 9); + FF1(cc, dd, ee, aa, bb, X[ 8], 11); + FF1(bb, cc, dd, ee, aa, X[ 9], 13); + FF1(aa, bb, cc, dd, ee, X[10], 14); + FF1(ee, aa, bb, cc, dd, X[11], 15); + FF1(dd, ee, aa, bb, cc, X[12], 6); + FF1(cc, dd, ee, aa, bb, X[13], 7); + FF1(bb, cc, dd, ee, aa, X[14], 9); + FF1(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + FF2(ee, aa, bb, cc, dd, X[ 7], 7); + FF2(dd, ee, aa, bb, cc, X[ 4], 6); + FF2(cc, dd, ee, aa, bb, X[13], 8); + FF2(bb, cc, dd, ee, aa, X[ 1], 13); + FF2(aa, bb, cc, dd, ee, X[10], 11); + FF2(ee, aa, bb, cc, dd, X[ 6], 9); + FF2(dd, ee, aa, bb, cc, X[15], 7); + FF2(cc, dd, ee, aa, bb, X[ 3], 15); + FF2(bb, cc, dd, ee, aa, X[12], 7); + FF2(aa, bb, cc, dd, ee, X[ 0], 12); + FF2(ee, aa, bb, cc, dd, X[ 9], 15); + FF2(dd, ee, aa, bb, cc, X[ 5], 9); + FF2(cc, dd, ee, aa, bb, X[ 2], 11); + FF2(bb, cc, dd, ee, aa, X[14], 7); + FF2(aa, bb, cc, dd, ee, X[11], 13); + FF2(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + FF3(dd, ee, aa, bb, cc, X[ 3], 11); + FF3(cc, dd, ee, aa, bb, X[10], 13); + FF3(bb, cc, dd, ee, aa, X[14], 6); + FF3(aa, bb, cc, dd, ee, X[ 4], 7); + FF3(ee, aa, bb, cc, dd, X[ 9], 14); + FF3(dd, ee, aa, bb, cc, X[15], 9); + FF3(cc, dd, ee, aa, bb, X[ 8], 13); + FF3(bb, cc, dd, ee, aa, X[ 1], 15); + FF3(aa, bb, cc, dd, ee, X[ 2], 14); + FF3(ee, aa, bb, cc, dd, X[ 7], 8); + FF3(dd, ee, aa, bb, cc, X[ 0], 13); + FF3(cc, dd, ee, aa, bb, X[ 6], 6); + FF3(bb, cc, dd, ee, aa, X[13], 5); + FF3(aa, bb, cc, dd, ee, X[11], 12); + FF3(ee, aa, bb, cc, dd, X[ 5], 7); + FF3(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + FF4(cc, dd, ee, aa, bb, X[ 1], 11); + FF4(bb, cc, dd, ee, aa, X[ 9], 12); + FF4(aa, bb, cc, dd, ee, X[11], 14); + FF4(ee, aa, bb, cc, dd, X[10], 15); + FF4(dd, ee, aa, bb, cc, X[ 0], 14); + FF4(cc, dd, ee, aa, bb, X[ 8], 15); + FF4(bb, cc, dd, ee, aa, X[12], 9); + FF4(aa, bb, cc, dd, ee, X[ 4], 8); + FF4(ee, aa, bb, cc, dd, X[13], 9); + FF4(dd, ee, aa, bb, cc, X[ 3], 14); + FF4(cc, dd, ee, aa, bb, X[ 7], 5); + FF4(bb, cc, dd, ee, aa, X[15], 6); + FF4(aa, bb, cc, dd, ee, X[14], 8); + FF4(ee, aa, bb, cc, dd, X[ 5], 6); + FF4(dd, ee, aa, bb, cc, X[ 6], 5); + FF4(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + FF5(bb, cc, dd, ee, aa, X[ 4], 9); + FF5(aa, bb, cc, dd, ee, X[ 0], 15); + FF5(ee, aa, bb, cc, dd, X[ 5], 5); + FF5(dd, ee, aa, bb, cc, X[ 9], 11); + FF5(cc, dd, ee, aa, bb, X[ 7], 6); + FF5(bb, cc, dd, ee, aa, X[12], 8); + FF5(aa, bb, cc, dd, ee, X[ 2], 13); + FF5(ee, aa, bb, cc, dd, X[10], 12); + FF5(dd, ee, aa, bb, cc, X[14], 5); + FF5(cc, dd, ee, aa, bb, X[ 1], 12); + FF5(bb, cc, dd, ee, aa, X[ 3], 13); + FF5(aa, bb, cc, dd, ee, X[ 8], 14); + FF5(ee, aa, bb, cc, dd, X[11], 11); + FF5(dd, ee, aa, bb, cc, X[ 6], 8); + FF5(cc, dd, ee, aa, bb, X[15], 5); + FF5(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + FFF5(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + FFF5(eee, aaa, bbb, ccc, ddd, X[14], 9); + FFF5(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + FFF5(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + FFF5(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + FFF5(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + FFF5(eee, aaa, bbb, ccc, ddd, X[11], 15); + FFF5(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + FFF5(ccc, ddd, eee, aaa, bbb, X[13], 7); + FFF5(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + FFF5(aaa, bbb, ccc, ddd, eee, X[15], 8); + FFF5(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + FFF5(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + FFF5(ccc, ddd, eee, aaa, bbb, X[10], 14); + FFF5(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + FFF5(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + FFF4(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + FFF4(ddd, eee, aaa, bbb, ccc, X[11], 13); + FFF4(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + FFF4(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + FFF4(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + FFF4(eee, aaa, bbb, ccc, ddd, X[13], 8); + FFF4(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + FFF4(ccc, ddd, eee, aaa, bbb, X[10], 11); + FFF4(bbb, ccc, ddd, eee, aaa, X[14], 7); + FFF4(aaa, bbb, ccc, ddd, eee, X[15], 7); + FFF4(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + FFF4(ddd, eee, aaa, bbb, ccc, X[12], 7); + FFF4(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + FFF4(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + FFF4(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + FFF4(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + FFF3(ddd, eee, aaa, bbb, ccc, X[15], 9); + FFF3(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + FFF3(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + FFF3(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + FFF3(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + FFF3(ddd, eee, aaa, bbb, ccc, X[14], 6); + FFF3(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + FFF3(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + FFF3(aaa, bbb, ccc, ddd, eee, X[11], 12); + FFF3(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + FFF3(ddd, eee, aaa, bbb, ccc, X[12], 5); + FFF3(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + FFF3(bbb, ccc, ddd, eee, aaa, X[10], 13); + FFF3(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + FFF3(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + FFF3(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + FFF2(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + FFF2(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + FFF2(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + FFF2(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + FFF2(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + FFF2(ccc, ddd, eee, aaa, bbb, X[11], 14); + FFF2(bbb, ccc, ddd, eee, aaa, X[15], 6); + FFF2(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + FFF2(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + FFF2(ddd, eee, aaa, bbb, ccc, X[12], 9); + FFF2(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + FFF2(bbb, ccc, ddd, eee, aaa, X[13], 9); + FFF2(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + FFF2(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + FFF2(ddd, eee, aaa, bbb, ccc, X[10], 15); + FFF2(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF1(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF1(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF1(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF1(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF1(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF1(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF1(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF1(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF1(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF1(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF1(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF1(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF1(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF1(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF1(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF1(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results into new state */ + ddd += cc + MDbuf[1]; + MDbuf[1] = MDbuf[2] + dd + eee; + MDbuf[2] = MDbuf[3] + ee + aaa; + MDbuf[3] = MDbuf[4] + aa + bbb; + MDbuf[4] = MDbuf[0] + bb + ccc; + MDbuf[0] = ddd; +} + +/********************************************************************/ +void MDfinish(word *MDbuf, byte *string, word lswlen, word mswlen) +/* The final value of the 5-word MDbuf array is calculated. + lswlen and mswlen contain, respectively, the least and most significant + 32 bits of the message bit length mod 2^64, and string is an incomplete + block containing the (lswlen mod 512) remaining message bits. + (In case the message is already a multiple of 512 bits, string + is not used.) The conversion of the 5-word final state MDbuf to + the 20-byte hash result using a Little-endian convention is the + responsibility of the calling function. +*/ +{ + size_t i, length; + byte mask; + word X[16]; + + /* clear 16-word message block */ + memset(X, 0, 16*sizeof(word)); + + /* copy (lswlen mod 512) bits from string into X */ + length = ((lswlen&511)+7)/8; /* number of bytes */ + mask = (lswlen&7) ? ((byte)1 << (lswlen&7)) - 1 : 0xff; + for (i=0; i>2] ^= (word) (*string&mask) << (8*(i&3)); + else + X[i>>2] ^= (word) *string++ << (8*(i&3)); + } + + /* append a single 1 */ + X[(lswlen>>5)&15] ^= (word)1 << (8*((lswlen>>3)&3)+7-(lswlen&7)); + + if ((lswlen & 511) > 447) { + /* length doesn't fit in this block anymore. + Compress, and put length in the next block */ + MDcompress(MDbuf, X); + memset(X, 0, 16*sizeof(word)); + } + /* append length in bits*/ + X[14] = lswlen; + X[15] = mswlen; + MDcompress(MDbuf, X); +} + +/************************ end of file rmd160.c **********************/ + diff --git a/src/bin/rmd160/rmd160.h b/src/bin/rmd160/rmd160.h new file mode 100644 index 0000000000..8e60a90825 --- /dev/null +++ b/src/bin/rmd160/rmd160.h @@ -0,0 +1,98 @@ +/********************************************************************\ + * FILE: rmd160.h + * CONTENTS: Header file for a sample C-implementation of the + * RIPEMD-160 hash-function. + * AUTHOR: Antoon Bosselaers, Dept. Electrical Eng.-ESAT/COSIC + * DATE: 1 March 1996 VERSION: 1.0 +\********************************************************************/ + +#ifndef RMD160H /* make sure this file is read only once */ +#define RMD160H + +/********************************************************************/ +/* Type definitions of an 8 and a 32-bit integer type, respectively. + Adapt these, if necessary, for your operating system and compiler +*/ +typedef unsigned char byte; /* unsigned 8-bit integer */ +typedef unsigned long word; /* unsigned 32-bit integer */ + +/********************************************************************/ +/* Macro definitions */ + +/* ROL(x, n) cyclically rotates x over n bits to the left + x must be of an unsigned 32 bits type and 0 <= n < 32. +*/ +#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* The five basic RIPEMD-160 functions F1(), F2(), F3(), F4(), and F5() +*/ +#define F1(x, y, z) ((x) ^ (y) ^ (z)) +#define F2(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define F3(x, y, z) (((x) | ~(y)) ^ (z)) +#define F4(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define F5(x, y, z) ((x) ^ ((y) | ~(z))) + +/* The ten basic RIPEMD-160 transformations FF1() through FFF5() +*/ +#define FF1(a, b, c, d, e, x, s) {\ + (a) += F1((b), (c), (d)) + (x);\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FF2(a, b, c, d, e, x, s) {\ + (a) += F2((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FF3(a, b, c, d, e, x, s) {\ + (a) += F3((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FF4(a, b, c, d, e, x, s) {\ + (a) += F4((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FF5(a, b, c, d, e, x, s) {\ + (a) += F5((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FFF1(a, b, c, d, e, x, s) {\ + (a) += F1((b), (c), (d)) + (x);\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FFF2(a, b, c, d, e, x, s) {\ + (a) += F2((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FFF3(a, b, c, d, e, x, s) {\ + (a) += F3((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FFF4(a, b, c, d, e, x, s) {\ + (a) += F4((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FFF5(a, b, c, d, e, x, s) {\ + (a) += F5((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +/********************************************************************/ +/* Function prototypes */ + +void MDinit(word *MDbuf); +void MDcompress(word *MDbuf, word *X); +void MDfinish(word *MDbuf, byte *string, word lswlen, word mswlen); + +#endif /* RMD160H */ + +/*********************** end of file rmd160.h ***********************/ +