home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume41
/
mdigest
/
part01
next >
Wrap
Internet Message Format
|
1994-03-24
|
53KB
From: M.Gream@uts.edu.au (Matthew Gream)
Newsgroups: comp.sources.misc
Subject: v41i137: mdigest - message digest library, Part01/03
Date: 28 Feb 1994 18:25:53 -0000
Sender: aem@aber.ac.uk
Approved: aem@aber.ac.uk
Message-ID: <csm-v41i137=mdigest.182540@aber.ac.uk>
X-Md4-Signature: 4c7b954030c2a62cf28c6787c57af528
Submitted-by: M.Gream@uts.edu.au (Matthew Gream)
Posting-number: Volume 41, Issue 137
Archive-name: mdigest/part01
Environment: C
#! /bin/sh
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents: README MANIFEST EXPORT haval.c mtest.c
# Wrapped by alecm@uk-usenet on Thu Feb 24 09:36:44 1994
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 1 (of 3)."'
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(10157 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
XMESSAGE DIGEST LIBRARY
X
XCopyright,
XMatthew Gream <M.Gream@uts.edu.au>,
XFebruary 1994.
X
X
X-- License
X
XPlease read 'license.txt', it is written for my larger project, but
Xapplies to this as well (it doesn't cover the items of sofware that
Xare not under my control, ie. the message digests themselves).
X
X
X-- Acknowledgements
X
XI acknowledge the use and inclusion of the following items of software
Xwithin the library:
X
X MD4, MD5 -- RSA Laboratories Inc.
X SHS -- Peter C. Gutmann, Colin Plumb.
X HAVAL -- Y. Zheng, J. Pieprzyk and J. Seberry.
X
X
X-- Overview
X
XIn working on a larger project, I've had to construct some generic
Xmodular handlers for message digest, encryption and compression methods.
XThe idea is that the one generic interface handler allows selection and
Xuse of any of the particular methods by a common set of interface
Xfunctions, thereby removing the idiosyncrasies of each particular
Xmethod.
X
XSome of the goals when writing this are to ensure it is flexible enough
Xto allow addition of new methods even external to this library, ie so an
Xapplication could selectively add or remove methods due to some other
Xinfluence. At the same, it must be easy to determine what methods are
Xcurrently available, and select them. Therefore, each method is known by
Xa string, ie "md5" for RSAs message-digest #5.
X
XAccess to the module is, similar to how most message digests are
Xstructure at the moment, via a context structure which keeps all the per
Xassociation static data within it. This allows concurrency.
X
XAnyway, the reason for release of this is that I gave it to a friend to
Xuse on something he was working on, he expressed delight at the
X'niftyness' of it, and suggested I make it available. Writing this
Xdocumentation and packaging it up for posting has already taken longer
Xthan writing the thing in the first place :-)
X
X
X-- Startup
X
XMost, just about all actually, functions have an enumerated return type
Xof 'err_code' which are defined in the header file (note: I had to hack
Xaround to move a few things into this header file, because in the larger
Xproject, it is more distributed). To be honest, err_code is a bit of a
Xmisnomer, it should really be ret_code, but anyway ... these give
Xinformation about function execution problems.
X
XBefore you use the module in anyway whatsoever, you want to call the
Xmodule initialisation function, this sets up internal tables and
Xregisters a few common message digests (md4,md5,shs,haval). The syntax
Xfor this is:
X
X md_mod_open ();
X
XEven though it does return an err_code, it is currently redundant. By
Xthe same token, after you've finished with the module, you're expected
Xto call:
X
X md_mod_close ();
X
Xwhich closes down and clears any used internal info. Naturally, a call
Xto /md_mod_open()/ will re-initialise it again.
X
X
X-- Lookup
X
XTo look at what methods are already registered, two functions so you can
X'walk the list' so to speak. To initialise the walk, call:
X
X md_list_init (word* state_var);
X
X/state_var/ is used as an index and used in the subsequent procedure of
Xreturning each registered identifier in turn, the syntax for this is:
X
X md_list_next (word* state_var, string ident);
X
XWhere string is a char array of minimum size /ident_sz/ (defined in the
Xheader -- currently 16). At each iteration, /state_var/ is updated and
Xthe next identifier is copied into /ident/. The return code here will be
X/err_ok/ until the end of list is reached (or you pass an incorrect
X/state_var/). For example, the following bit of code would list all the
Xcurrently registered methods:
X
X void list_methods ()
X {
X word s;
X char ident[ident_sz+1];
X
X md_list_init (&s);
X while (md_list_next (&s, ident) == err_ok)
X printf ("-> %s\n", ident);
X }
X
X-- Registration/Deregistration
X
XIf you wish to add a custom digest to the module, you need to call the
Xregistration process. First, your message digest needs to provide the
Xfollowing functions (examine, say, md4-if.c to see how this works):
X
X create() : this takes as argument the message digest
X context and allocates/initialises the internal
X private data store.
X
X destroy() : takes a context as argument and deallocates the
X the internal private data store.
X
X register() : takes and info structure as it's argument and
X fills out all the function call handlers to
X those just described above.
X
X deregister() : can be NULL, if not this is called when the
X module is deregistered and takes an info struct
X as it's argument.
X
X [the user called functions that actually do work:]
X
X init() : called with the private data structure as
X argument and expected to initialise state
X information ready to start calculating a digest.
X
X update () : takes private data structure, data and it's
X length to be used to update the digest.
X
X final () : takes private data structure and a storage area
X to copy the digest too when all update()s have
X been finished.
X
XTo register, you call the registration function with the ASCII string
Xname of the method and the above registration function, the syntax for
Xthis is:
X
X md_register (string ident, function register);
X
X/md_register()/ will then check that an identifier of the same name
Xdoesn't exist, and if so, allocate new storage for an info structure on
Xthe list and call the register function so it can fill in the details.
XAgain, a much better explanation can be had if you read the source code
X:-).
X
XDeregistration is even easier, just call the deregistration function
Xwith the identifier to remove, the syntax for this is:
X
X md_deregister (string ident);
X
XAs a practical example, say you wanted to register a crc32 message
Xdigest, you'd have code something to the effect of:
X
X extern err_code crc32_register ();
X
X if (md_register ("crc32", crc32_register) != err_ok)
X {
X ...
X }
X
Xand for deregistration:
X
X (void)md_deregister ("crc32");
X
X
X-- Operation
X
XPutting aside the administrative details of initialisation and
Xregistration, using the module from an application is exceeding simple.
XYou first need to call /md_open()/ with an empty context structure, and
Xthe requested digest to use. From then on, you can use successive
Xiterations of /md_init()/ to initialise the digest, /md_update()/ to
Xupdate the digest with new data, and /md_final()/ to return the digest.
XAgain, a practical example is the easiest. Consider the following
Xfunction to take a files as input and determine the digest using md4.
X
X
X /* returns size of digest if ok, or -1 if error occured
X */
X int md_of_file (filename, digest, digest_sz)
X char* filename; /* filename to work on */
X char* digest; /* where to place the digest */
X int digest_sz; /* how much space is avail */
X {
X int f;
X int i, j, k;
X char buf[8192];
X md_ctx ctx;
X
X if (md_mod_open () != err_ok)
X return -1; /* something failed at init */
X
X if (md_open (&ctx, "md4") != err_ok)
X return -1; /* md4 isn't registered */
X
X if (digest_sz < md_hash_sz (&ctx))
X return -1; /* not enough space for the digest */
X
X if ((f = open (filename, O_RDONLY)) < 0)
X return -1; /* can't open file */
X
X md_init (&ctx); /* initialisation */
X
X do /* read and update */
X {
X j = read (f, buf, 8192);
X if (j > 0)
X md_update (&ctx, buf, j);
X }
X while (j == 8192); /* until exhausted input */
X
X close (f);
X
X md_final (&ctx, digest); /* compute and place in buffer */
X j = md_hash_sz (&ctx); /* store size of hash before close */
X
X md_close (&ctx); /* close the context */
X
X md_mod_close (); /* shutdown the module */
X
X return j; /* return size of hash */
X }
X
X
X-- Building
X
XType make. Should work on most architectures as there is little, if no,
Xarchitecture dependent code. I've tested it on linux under gcc and SunOS
Xunder both gcc and cc, no problems at all. I haven't tried it on MSDOS
Xyet though.
X
XIf you want to modify which digests are included and/or which are loaded
Xat module open, the add or remove the object files from the makefile,
Xand edit the lines in mdigest.c in /md_mod_open()/ add or subtract
X/md_register()/s.
X
X
X-- Testing
X
XI've not done exhaustive testing on it, but running test suites and
Xcomparing against vanilla digests, all seems ok. Anyway, it's so damn
Xsmall there isn't really much that can go wrong :-) [famous last
Xwords ...].
X
X
X-- Included software
X
X > mfile.
X
X program which takes as arguments a number of files to calculate message
X digests of. Each digest can be explicitly requested, or if none are,
X then the default is to calculate all of them. This is used to make the
X CHECKSUMS file.
X
X > mtest.
X
X runs test suites relevant to particular message digests.
X
X-- Bugs
X
XNone (so far).
X
X-- Finally
X
XI had to reverse the arguments to some of the message digests. Theres a
Xbit of inconsistency because the init() and update() functions take a
Xcontext as first parameter, but the final() doesn't. I guess it's just
Xmy pedantic genericism that does it, but hey.
X
Xps. I hate writing documentation, so excuse the above if it seems too
Xcryptic.
X
X
END_OF_FILE
if test 10157 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(785 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X File Name Archive # Description
X----------------------------------------------------------
XREADME 1
XMANIFEST 1
XCHECKSUMS 3
XEXPORT 1
XMakefile 3
Xhaval-if.c 3
Xhaval.c 1
Xhaval.h 3
Xlicense.txt 3
Xmd4-if.c 3
Xmd4.c 2
Xmd4.h 3
Xmd5-if.c 3
Xmd5.c 2
Xmd5.h 3
Xmdigest.c 2
Xmdigest.h 3
Xmfile.c 2
Xmtest.c 1
Xshs-if.c 3
Xshs.c 2
Xshs.h 3
Xutility.c 3
END_OF_FILE
if test 785 -ne `wc -c <'MANIFEST'`; then
echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'EXPORT' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'EXPORT'\"
else
echo shar: Extracting \"'EXPORT'\" \(97 characters\)
sed "s/^X//" >'EXPORT' <<'END_OF_FILE'
X
XMessage digests are not covered by ITAR. Hence, export of this
Xproduct from the USA is legal.
X
END_OF_FILE
if test 97 -ne `wc -c <'EXPORT'`; then
echo shar: \"'EXPORT'\" unpacked with wrong size!
fi
# end of 'EXPORT'
fi
if test -f 'haval.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'haval.c'\"
else
echo shar: Extracting \"'haval.c'\" \(26139 characters\)
sed "s/^X//" >'haval.c' <<'END_OF_FILE'
X
X/* -- derived from original haval.c, changes are:
X * -- mgream: added run time endian checks, instead of precompiled
X * -- mgream: changed function args from ansi (for compat)
X *
X * haval.c: specifies the routines in the HAVAL (V.1) hashing library.
X *
X * HAVAL is a one-way hashing algorithm with the following
X * collision-resistant property:
X * It is computationally infeasible to find two or more
X * messages that are hashed into the same fingerprint.
X *
X * Reference:
X * Y. Zheng, J. Pieprzyk and J. Seberry:
X * ``HAVAL --- a one-way hashing algorithm with variable
X * length of output'', Advances in Cryptology --- AUSCRYPT'92,
X * Lecture Notes in Computer Science, Springer-Verlag, 1993.
X *
X * Descriptions:
X * - haval_string: hash a string
X * - haval_file: hash a file
X * - haval_stdin: filter -- hash input from the stdin device
X * - haval_hash: hash a string of specified length
X * (Haval_hash is used in conjunction with
X * haval_start & haval_end.)
X * - haval_hash_block: hash a 32-word block
X * - haval_start: initialization
X * - haval_end: finalization
X *
X * Author: Yuliang Zheng
X * Department of Computer Science
X * University of Wollongong
X * Wollongong, NSW 2522, Australia
X * Email: yuliang@cs.uow.edu.au
X * Voice: +61 42 21 4331 (office)
X *
X * Date: June 1993
X *
X * Copyright (C) 1993 by C^3SR. All rights reserved.
X * This program may not be sold or used as inducement to
X * buy a product without the written permission of C^3SR.
X */
X
X#include <stdio.h>
X#include <memory.h>
X#include "haval.h"
X
Xstatic int endian = 0; /* 0 = little, 1 = big */
X
X#define VERSION 1 /* current version number */
X
Xvoid haval_start (); /* initialization */
Xvoid haval_hash (); /* updating routine */
Xvoid haval_end (); /* finalization */
Xvoid haval_hash_block (); /* hash a 32-word block */
Xstatic void haval_tailor (); /* folding the last output */
X
Xstatic unsigned char padding[128] = { /* constants for padding */
X0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
X};
X
X#define f_1(x6, x5, x4, x3, x2, x1, x0) \
X ((x1) & ((x0) ^ (x4)) ^ (x2) & (x5) ^ \
X (x3) & (x6) ^ (x0))
X
X#define f_2(x6, x5, x4, x3, x2, x1, x0) \
X ((x2) & ((x1) & ~(x3) ^ (x4) & (x5) ^ (x6) ^ (x0)) ^ \
X (x4) & ((x1) ^ (x5)) ^ (x3) & (x5) ^ (x0))
X
X#define f_3(x6, x5, x4, x3, x2, x1, x0) \
X ((x3) & ((x1) & (x2) ^ (x6) ^ (x0)) ^ \
X (x1) & (x4) ^ (x2) & (x5) ^ (x0))
X
X#define f_4(x6, x5, x4, x3, x2, x1, x0) \
X ((x4) & ((x5) & ~(x2) ^ (x3) & ~(x6) ^ (x1) ^ (x6) ^ (x0)) ^ \
X (x3) & ((x1) & (x2) ^ (x5) ^ (x6)) ^ \
X (x2) & (x6) ^ (x0))
X
X#define f_5(x6, x5, x4, x3, x2, x1, x0) \
X ((x0) & ((x1) & (x2) & (x3) ^ ~(x5)) ^ \
X (x1) & (x4) ^ (x2) & (x5) ^ (x3) & (x6))
X
X/*
X * Permutations phi_{i,j}, i=3,4,5, j=1,...,i.
X *
X * PASS = 3:
X * 6 5 4 3 2 1 0
X * | | | | | | | (replaced by)
X * phi_{3,1}: 1 0 3 5 6 2 4
X * phi_{3,2}: 4 2 1 0 5 3 6
X * phi_{3,3}: 6 1 2 3 4 5 0
X *
X * PASS = 4:
X * 6 5 4 3 2 1 0
X * | | | | | | | (replaced by)
X * phi_{4,1}: 2 6 1 4 5 3 0
X * phi_{4,2}: 3 5 2 0 1 6 4
X * phi_{4,3}: 1 4 3 6 0 2 5
X * phi_{4,4}: 6 4 0 5 2 1 3
X *
X * PASS = 5:
X * 6 5 4 3 2 1 0
X * | | | | | | | (replaced by)
X * phi_{5,1}: 3 4 1 0 5 2 6
X * phi_{5,2}: 6 2 1 0 3 4 5
X * phi_{5,3}: 2 6 0 4 3 1 5
X * phi_{5,4}: 1 5 3 2 0 4 6
X * phi_{5,5}: 2 5 0 6 4 3 1
X */
X
X#if PASS == 3
X#define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \
X f_1(x1, x0, x3, x5, x6, x2, x4)
X#elif PASS == 4
X#define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \
X f_1(x2, x6, x1, x4, x5, x3, x0)
X#else
X#define Fphi_1(x6, x5, x4, x3, x2, x1, x0) \
X f_1(x3, x4, x1, x0, x5, x2, x6)
X#endif
X
X#if PASS == 3
X#define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \
X f_2(x4, x2, x1, x0, x5, x3, x6)
X#elif PASS == 4
X#define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \
X f_2(x3, x5, x2, x0, x1, x6, x4)
X#else
X#define Fphi_2(x6, x5, x4, x3, x2, x1, x0) \
X f_2(x6, x2, x1, x0, x3, x4, x5)
X#endif
X
X#if PASS == 3
X#define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \
X f_3(x6, x1, x2, x3, x4, x5, x0)
X#elif PASS == 4
X#define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \
X f_3(x1, x4, x3, x6, x0, x2, x5)
X#else
X#define Fphi_3(x6, x5, x4, x3, x2, x1, x0) \
X f_3(x2, x6, x0, x4, x3, x1, x5)
X#endif
X
X#if PASS == 4
X#define Fphi_4(x6, x5, x4, x3, x2, x1, x0) \
X f_4(x6, x4, x0, x5, x2, x1, x3)
X#else
X#define Fphi_4(x6, x5, x4, x3, x2, x1, x0) \
X f_4(x1, x5, x3, x2, x0, x4, x6)
X#endif
X
X#define Fphi_5(x6, x5, x4, x3, x2, x1, x0) \
X f_5(x2, x5, x0, x6, x4, x3, x1)
X
X#define rotate_right(x, n) (((x) >> (n)) | ((x) << (32-(n))))
X
X#define FF_1(x7, x6, x5, x4, x3, x2, x1, x0, w) { \
X register haval_word temp = Fphi_1(x6, x5, x4, x3, x2, x1, x0); \
X (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w); \
X }
X
X#define FF_2(x7, x6, x5, x4, x3, x2, x1, x0, w, c) { \
X register haval_word temp = Fphi_2(x6, x5, x4, x3, x2, x1, x0); \
X (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c); \
X }
X
X#define FF_3(x7, x6, x5, x4, x3, x2, x1, x0, w, c) { \
X register haval_word temp = Fphi_3(x6, x5, x4, x3, x2, x1, x0); \
X (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c); \
X }
X
X#define FF_4(x7, x6, x5, x4, x3, x2, x1, x0, w, c) { \
X register haval_word temp = Fphi_4(x6, x5, x4, x3, x2, x1, x0); \
X (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c); \
X }
X
X#define FF_5(x7, x6, x5, x4, x3, x2, x1, x0, w, c) { \
X register haval_word temp = Fphi_5(x6, x5, x4, x3, x2, x1, x0); \
X (x7) = rotate_right(temp, 7) + rotate_right((x7), 11) + (w) + (c); \
X }
X
X/*
X * translate every four characters into a word.
X * assume the number of characters is a multiple of four.
X */
X#define ch2uint(string, word, slen) { \
X unsigned char *sp = string; \
X haval_word *wp = word; \
X while (sp < (string) + (slen)) { \
X *wp++ = (haval_word)*sp | \
X ((haval_word)*(sp+1) << 8) | \
X ((haval_word)*(sp+2) << 16) | \
X ((haval_word)*(sp+3) << 24); \
X sp += 4; \
X } \
X}
X
X/* translate each word into four characters */
X#define uint2ch(word, string, wlen) { \
X haval_word *wp = word; \
X unsigned char *sp = string; \
X while (wp < (word) + (wlen)) { \
X *(sp++) = (unsigned char)( *wp & 0xFF); \
X *(sp++) = (unsigned char)((*wp >> 8) & 0xFF); \
X *(sp++) = (unsigned char)((*wp >> 16) & 0xFF); \
X *(sp++) = (unsigned char)((*wp >> 24) & 0xFF); \
X wp++; \
X } \
X}
X
X/* initialization */
Xvoid haval_start (state)
X haval_state *state;
X{
X state->count[0] = state->count[1] = 0; /* clear count */
X state->fingerprint[0] = 0x243F6A88; /* initial fingerprint */
X state->fingerprint[1] = 0x85A308D3;
X state->fingerprint[2] = 0x13198A2E;
X state->fingerprint[3] = 0x03707344;
X state->fingerprint[4] = 0xA4093822;
X state->fingerprint[5] = 0x299F31D0;
X state->fingerprint[6] = 0x082EFA98;
X state->fingerprint[7] = 0xEC4E6C89;
X
X /* from shs.c
X *
X * Find out what the byte order is on this machine.
X * Big endian is for machines that place the most significant byte
X * first (eg. Sun SPARC). Little endian is for machines that place
X * the least significant byte first (eg. VAX).
X *
X * We figure out the byte order by stuffing a 2 byte string into a
X * short and examining the left byte. '@' = 0x40 and 'P' = 0x50
X * If the left byte is the 'high' byte, then it is 'big endian'.
X * If the left byte is the 'low' byte, then the machine is 'little
X * endian'.
X *
X * -- Shawn A. Clifford (sac@eng.ufl.edu)
X */
X
X if ((*(unsigned short *) ("@P") >> 8) == '@')
X endian = 1;
X else
X endian = 0;
X
X}
X
X/*
X * hash a string of specified length.
X * to be used in conjunction with haval_start and haval_end.
X */
Xvoid haval_hash (state, str, str_len)
X haval_state* state;
X unsigned char *str;
X unsigned int str_len;
X{
X unsigned int i,
X rmd_len,
X fill_len;
X
X /* calculate the number of bytes in the remainder */
X rmd_len = (unsigned int)((state->count[0] >> 3) & 0x7F);
X fill_len = 128 - rmd_len;
X
X /* update the number of bits */
X if ((state->count[0] += (haval_word)str_len << 3)
X < ((haval_word)str_len << 3)) {
X state->count[1]++;
X }
X state->count[1] += (haval_word)str_len >> 29;
X
X/*#ifdef LITTLE_ENDIAN*/
X if (endian == 0) {
X
X /* hash as many blocks as possible */
X if (rmd_len + str_len >= 128) {
X memcpy (((unsigned char *)state->block)+rmd_len, str, fill_len);
X haval_hash_block (state);
X for (i = fill_len; i + 127 < str_len; i += 128){
X memcpy ((unsigned char *)state->block, str+i, 128);
X haval_hash_block (state);
X }
X rmd_len = 0;
X } else {
X i = 0;
X }
X memcpy (((unsigned char *)state->block)+rmd_len, str+i, str_len-i);
X
X/*#else*/
X } else {
X
X /* hash as many blocks as possible */
X if (rmd_len + str_len >= 128) {
X memcpy (&state->remainder[rmd_len], str, fill_len);
X ch2uint(state->remainder, state->block, 128);
X haval_hash_block (state);
X for (i = fill_len; i + 127 < str_len; i += 128){
X memcpy (state->remainder, str+i, 128);
X ch2uint(state->remainder, state->block, 128);
X haval_hash_block (state);
X }
X rmd_len = 0;
X } else {
X i = 0;
X }
X /* save the remaining input chars */
X memcpy (&state->remainder[rmd_len], str+i, str_len-i);
X
X/*#endif*/
X }
X
X}
X
X/* finalization */
Xvoid haval_end (state, final_fpt)
X haval_state * state;
X unsigned char final_fpt[FPTLEN >> 3];
X{
X unsigned char tail[10];
X unsigned int rmd_len, pad_len;
X
X /*
X * save the version number, the number of passes, the fingerprint
X * length and the number of bits in the unpadded message.
X */
X tail[0] = (unsigned char)(((FPTLEN & 0x3) << 6) |
X ((PASS & 0x7) << 3) |
X (VERSION & 0x7));
X tail[1] = (unsigned char)((FPTLEN >> 2) & 0xFF);
X uint2ch (state->count, &tail[2], 2);
X
X /* pad out to 118 mod 128 */
X rmd_len = (unsigned int)((state->count[0] >> 3) & 0x7f);
X pad_len = (rmd_len < 118) ? (118 - rmd_len) : (246 - rmd_len);
X haval_hash (state, padding, pad_len);
X
X /*
X * append the version number, the number of passes,
X * the fingerprint length and the number of bits
X */
X haval_hash (state, tail, 10);
X
X /* tailor the last output */
X haval_tailor(state);
X
X /* translate and save the final fingerprint */
X uint2ch (state->fingerprint, final_fpt, FPTLEN >> 5);
X
X /* clear the state information */
X memset ((unsigned char *)state, 0, sizeof (*state));
X}
X
X/* hash a 32-word block */
Xvoid haval_hash_block (state)
X haval_state* state;
X{
X register haval_word t0 = state->fingerprint[0], /* make use of */
X t1 = state->fingerprint[1], /* internal registers */
X t2 = state->fingerprint[2],
X t3 = state->fingerprint[3],
X t4 = state->fingerprint[4],
X t5 = state->fingerprint[5],
X t6 = state->fingerprint[6],
X t7 = state->fingerprint[7],
X *w = state->block;
X
X /* Pass 1 */
X FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w ));
X FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 1));
X FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 2));
X FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 3));
X FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 4));
X FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 5));
X FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 6));
X FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 7));
X
X FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 8));
X FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9));
X FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+10));
X FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+11));
X FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+12));
X FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+13));
X FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+14));
X FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+15));
X
X FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+16));
X FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+17));
X FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+18));
X FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+19));
X FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+20));
X FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+21));
X FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+22));
X FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+23));
X
X FF_1(t7, t6, t5, t4, t3, t2, t1, t0, *(w+24));
X FF_1(t6, t5, t4, t3, t2, t1, t0, t7, *(w+25));
X FF_1(t5, t4, t3, t2, t1, t0, t7, t6, *(w+26));
X FF_1(t4, t3, t2, t1, t0, t7, t6, t5, *(w+27));
X FF_1(t3, t2, t1, t0, t7, t6, t5, t4, *(w+28));
X FF_1(t2, t1, t0, t7, t6, t5, t4, t3, *(w+29));
X FF_1(t1, t0, t7, t6, t5, t4, t3, t2, *(w+30));
X FF_1(t0, t7, t6, t5, t4, t3, t2, t1, *(w+31));
X
X /* Pass 2 */
X FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 5), 0x452821E6);
X FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+14), 0x38D01377);
X FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+26), 0xBE5466CF);
X FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+18), 0x34E90C6C);
X FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+11), 0xC0AC29B7);
X FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+28), 0xC97C50DD);
X FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 7), 0x3F84D5B5);
X FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+16), 0xB5470917);
X
X FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w ), 0x9216D5D9);
X FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+23), 0x8979FB1B);
X FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+20), 0xD1310BA6);
X FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+22), 0x98DFB5AC);
X FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 1), 0x2FFD72DB);
X FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+10), 0xD01ADFB7);
X FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 4), 0xB8E1AFED);
X FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 8), 0x6A267E96);
X
X FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+30), 0xBA7C9045);
X FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 3), 0xF12C7F99);
X FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0x24A19947);
X FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 9), 0xB3916CF7);
X FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x0801F2E2);
X FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+24), 0x858EFC16);
X FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+29), 0x636920D8);
X FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 6), 0x71574E69);
X
X FF_2(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0xA458FEA3);
X FF_2(t6, t5, t4, t3, t2, t1, t0, t7, *(w+12), 0xF4933D7E);
X FF_2(t5, t4, t3, t2, t1, t0, t7, t6, *(w+15), 0x0D95748F);
X FF_2(t4, t3, t2, t1, t0, t7, t6, t5, *(w+13), 0x728EB658);
X FF_2(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 2), 0x718BCD58);
X FF_2(t2, t1, t0, t7, t6, t5, t4, t3, *(w+25), 0x82154AEE);
X FF_2(t1, t0, t7, t6, t5, t4, t3, t2, *(w+31), 0x7B54A41D);
X FF_2(t0, t7, t6, t5, t4, t3, t2, t1, *(w+27), 0xC25A59B5);
X
X /* Pass 3 */
X FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0x9C30D539);
X FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9), 0x2AF26013);
X FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 4), 0xC5D1B023);
X FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+20), 0x286085F0);
X FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+28), 0xCA417918);
X FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+17), 0xB8DB38EF);
X FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 8), 0x8E79DCB0);
X FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+22), 0x603A180E);
X
X FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+29), 0x6C9E0E8B);
X FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+14), 0xB01E8A3E);
X FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+25), 0xD71577C1);
X FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+12), 0xBD314B27);
X FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+24), 0x78AF2FDA);
X FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+30), 0x55605C60);
X FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+16), 0xE65525F3);
X FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+26), 0xAA55AB94);
X
X FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+31), 0x57489862);
X FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+15), 0x63E81440);
X FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 7), 0x55CA396A);
X FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 3), 0x2AAB10B6);
X FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 1), 0xB4CC5C34);
X FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w ), 0x1141E8CE);
X FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+18), 0xA15486AF);
X FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+27), 0x7C72E993);
X
X FF_3(t7, t6, t5, t4, t3, t2, t1, t0, *(w+13), 0xB3EE1411);
X FF_3(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 6), 0x636FBC2A);
X FF_3(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0x2BA9C55D);
X FF_3(t4, t3, t2, t1, t0, t7, t6, t5, *(w+10), 0x741831F6);
X FF_3(t3, t2, t1, t0, t7, t6, t5, t4, *(w+23), 0xCE5C3E16);
X FF_3(t2, t1, t0, t7, t6, t5, t4, t3, *(w+11), 0x9B87931E);
X FF_3(t1, t0, t7, t6, t5, t4, t3, t2, *(w+ 5), 0xAFD6BA33);
X FF_3(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 2), 0x6C24CF5C);
X
X#if PASS >= 4
X /* Pass 4. executed only when PASS =4 or 5 */
X FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+24), 0x7A325381);
X FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 4), 0x28958677);
X FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w ), 0x3B8F4898);
X FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+14), 0x6B4BB9AF);
X FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 2), 0xC4BFE81B);
X FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 7), 0x66282193);
X FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+28), 0x61D809CC);
X FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+23), 0xFB21A991);
X
X FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+26), 0x487CAC60);
X FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 6), 0x5DEC8032);
X FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+30), 0xEF845D5D);
X FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+20), 0xE98575B1);
X FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+18), 0xDC262302);
X FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+25), 0xEB651B88);
X FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+19), 0x23893E81);
X FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 3), 0xD396ACC5);
X
X FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+22), 0x0F6D6FF3);
X FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+11), 0x83F44239);
X FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+31), 0x2E0B4482);
X FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+21), 0xA4842004);
X FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 8), 0x69C8F04A);
X FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+27), 0x9E1F9B5E);
X FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+12), 0x21C66842);
X FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+ 9), 0xF6E96C9A);
X
X FF_4(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 1), 0x670C9C61);
X FF_4(t6, t5, t4, t3, t2, t1, t0, t7, *(w+29), 0xABD388F0);
X FF_4(t5, t4, t3, t2, t1, t0, t7, t6, *(w+ 5), 0x6A51A0D2);
X FF_4(t4, t3, t2, t1, t0, t7, t6, t5, *(w+15), 0xD8542F68);
X FF_4(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x960FA728);
X FF_4(t2, t1, t0, t7, t6, t5, t4, t3, *(w+10), 0xAB5133A3);
X FF_4(t1, t0, t7, t6, t5, t4, t3, t2, *(w+16), 0x6EEF0B6C);
X FF_4(t0, t7, t6, t5, t4, t3, t2, t1, *(w+13), 0x137A3BE4);
X#endif
X
X#if PASS == 5
X /* Pass 5. executed only when PASS = 5 */
X FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+27), 0xBA3BF050);
X FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 3), 0x7EFB2A98);
X FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+21), 0xA1F1651D);
X FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+26), 0x39AF0176);
X FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+17), 0x66CA593E);
X FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+11), 0x82430E88);
X FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+20), 0x8CEE8619);
X FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+29), 0x456F9FB4);
X
X FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+19), 0x7D84A5C3);
X FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w ), 0x3B8B5EBE);
X FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+12), 0xE06F75D8);
X FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+ 7), 0x85C12073);
X FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+13), 0x401A449F);
X FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 8), 0x56C16AA6);
X FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+31), 0x4ED3AA62);
X FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+10), 0x363F7706);
X
X FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 5), 0x1BFEDF72);
X FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+ 9), 0x429B023D);
X FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+14), 0x37D0D724);
X FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+30), 0xD00A1248);
X FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+18), 0xDB0FEAD3);
X FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 6), 0x49F1C09B);
X FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+28), 0x075372C9);
X FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+24), 0x80991B7B);
X
X FF_5(t7, t6, t5, t4, t3, t2, t1, t0, *(w+ 2), 0x25D479D8);
X FF_5(t6, t5, t4, t3, t2, t1, t0, t7, *(w+23), 0xF6E8DEF7);
X FF_5(t5, t4, t3, t2, t1, t0, t7, t6, *(w+16), 0xE3FE501A);
X FF_5(t4, t3, t2, t1, t0, t7, t6, t5, *(w+22), 0xB6794C3B);
X FF_5(t3, t2, t1, t0, t7, t6, t5, t4, *(w+ 4), 0x976CE0BD);
X FF_5(t2, t1, t0, t7, t6, t5, t4, t3, *(w+ 1), 0x04C006BA);
X FF_5(t1, t0, t7, t6, t5, t4, t3, t2, *(w+25), 0xC1A94FB6);
X FF_5(t0, t7, t6, t5, t4, t3, t2, t1, *(w+15), 0x409F60C4);
X#endif
X
X state->fingerprint[0] += t0;
X state->fingerprint[1] += t1;
X state->fingerprint[2] += t2;
X state->fingerprint[3] += t3;
X state->fingerprint[4] += t4;
X state->fingerprint[5] += t5;
X state->fingerprint[6] += t6;
X state->fingerprint[7] += t7;
X}
X
X/* tailor the last output */
Xstatic void haval_tailor (state)
X haval_state * state;
X{
X haval_word temp;
X
X#if FPTLEN == 128
X temp = (state->fingerprint[7] & 0x000000FF) |
X (state->fingerprint[6] & 0xFF000000) |
X (state->fingerprint[5] & 0x00FF0000) |
X (state->fingerprint[4] & 0x0000FF00);
X state->fingerprint[0] += rotate_right(temp, 8);
X
X temp = (state->fingerprint[7] & 0x0000FF00) |
X (state->fingerprint[6] & 0x000000FF) |
X (state->fingerprint[5] & 0xFF000000) |
X (state->fingerprint[4] & 0x00FF0000);
X state->fingerprint[1] += rotate_right(temp, 16);
X
X temp = (state->fingerprint[7] & 0x00FF0000) |
X (state->fingerprint[6] & 0x0000FF00) |
X (state->fingerprint[5] & 0x000000FF) |
X (state->fingerprint[4] & 0xFF000000);
X state->fingerprint[2] += rotate_right(temp, 24);
X
X temp = (state->fingerprint[7] & 0xFF000000) |
X (state->fingerprint[6] & 0x00FF0000) |
X (state->fingerprint[5] & 0x0000FF00) |
X (state->fingerprint[4] & 0x000000FF);
X state->fingerprint[3] += temp;
X
X#elif FPTLEN == 160
X temp = (state->fingerprint[7] & (haval_word)0x3F) |
X (state->fingerprint[6] & ((haval_word)0x7F << 25)) |
X (state->fingerprint[5] & ((haval_word)0x3F << 19));
X state->fingerprint[0] += rotate_right(temp, 19);
X
X temp = (state->fingerprint[7] & ((haval_word)0x3F << 6)) |
X (state->fingerprint[6] & (haval_word)0x3F) |
X (state->fingerprint[5] & ((haval_word)0x7F << 25));
X state->fingerprint[1] += rotate_right(temp, 25);
X
X temp = (state->fingerprint[7] & ((haval_word)0x7F << 12)) |
X (state->fingerprint[6] & ((haval_word)0x3F << 6)) |
X (state->fingerprint[5] & (haval_word)0x3F);
X state->fingerprint[2] += temp;
X
X temp = (state->fingerprint[7] & ((haval_word)0x3F << 19)) |
X (state->fingerprint[6] & ((haval_word)0x7F << 12)) |
X (state->fingerprint[5] & ((haval_word)0x3F << 6));
X state->fingerprint[3] += temp >> 6;
X
X temp = (state->fingerprint[7] & ((haval_word)0x7F << 25)) |
X (state->fingerprint[6] & ((haval_word)0x3F << 19)) |
X (state->fingerprint[5] & ((haval_word)0x7F << 12));
X state->fingerprint[4] += temp >> 12;
X
X#elif FPTLEN == 192
X temp = (state->fingerprint[7] & (haval_word)0x1F) |
X (state->fingerprint[6] & ((haval_word)0x3F << 26));
X state->fingerprint[0] += rotate_right(temp, 26);
X
X temp = (state->fingerprint[7] & ((haval_word)0x1F << 5)) |
X (state->fingerprint[6] & (haval_word)0x1F);
X state->fingerprint[1] += temp;
X
X temp = (state->fingerprint[7] & ((haval_word)0x3F << 10)) |
X (state->fingerprint[6] & ((haval_word)0x1F << 5));
X state->fingerprint[2] += temp >> 5;
X
X temp = (state->fingerprint[7] & ((haval_word)0x1F << 16)) |
X (state->fingerprint[6] & ((haval_word)0x3F << 10));
X state->fingerprint[3] += temp >> 10;
X
X temp = (state->fingerprint[7] & ((haval_word)0x1F << 21)) |
X (state->fingerprint[6] & ((haval_word)0x1F << 16));
X state->fingerprint[4] += temp >> 16;
X
X temp = (state->fingerprint[7] & ((haval_word)0x3F << 26)) |
X (state->fingerprint[6] & ((haval_word)0x1F << 21));
X state->fingerprint[5] += temp >> 21;
X
X#elif FPTLEN == 224
X state->fingerprint[0] += (state->fingerprint[7] >> 27) & 0x1F;
X state->fingerprint[1] += (state->fingerprint[7] >> 22) & 0x1F;
X state->fingerprint[2] += (state->fingerprint[7] >> 18) & 0x0F;
X state->fingerprint[3] += (state->fingerprint[7] >> 13) & 0x1F;
X state->fingerprint[4] += (state->fingerprint[7] >> 9) & 0x0F;
X state->fingerprint[5] += (state->fingerprint[7] >> 4) & 0x1F;
X state->fingerprint[6] += state->fingerprint[7] & 0x0F;
X#endif
X}
X
X
END_OF_FILE
if test 26139 -ne `wc -c <'haval.c'`; then
echo shar: \"'haval.c'\" unpacked with wrong size!
fi
# end of 'haval.c'
fi
if test -f 'mtest.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mtest.c'\"
else
echo shar: Extracting \"'mtest.c'\" \(11052 characters\)
sed "s/^X//" >'mtest.c' <<'END_OF_FILE'
X
X/* -------------------------------------------------------------------- */
X/* */
X/* Secure Asyncronous Communications Subsystem (SACS) */
X/* (C) 1994 Matthew Gream <M.Gream@uts.edu.au> */
X/* */
X/* You have been given a limited license to use and distribute this */
X/* library. You should have received this license with the original */
X/* release package of this library, named "license.txt" and entitled */
X/* "SACS SOFTWARE LICENSE". In the event that you have not read or */
X/* understood this license, regardless of reason, you may do nothing */
X/* with this library other than read it for self-awareness. */
X/* */
X/* -------------------------------------------------------------------- */
X
X/* $Id: mfile.c%v 0.90 1994/02/22 20:51:46 matt Exp $
X */
X
X/*
X * File: mtest.c
X * Description: test md4, md5, shs and (if added) other digests
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <unistd.h>
X#include <fcntl.h>
X
X#include <mdigest.h>
X
X/* -------------------------------------------------------------------- */
X
Xstatic string digest_to_hex ();
Xstatic word test_md4 ();
Xstatic word test_md5 ();
Xstatic word test_shs ();
Xstatic word test_haval ();
X
X/* -------------------------------------------------------------------- */
X
Xtypedef struct
X {
X string ident;
X word (*test)();
X } test_func;
X
Xtest_func testable_mds[] =
X {
X { "md4", test_md4 },
X { "md5", test_md5 },
X { "shs", test_shs },
X { "haval", test_haval },
X { NULL, NULL },
X };
X
X/* -------------------------------------------------------------------- */
X/* function : main */
X/* -------------------------------------------------------------------- */
Xvoid
Xmain (argc, argv)
X int argc;
X char** argv;
X{
X word c;
X word s;
X md_ctx ctx;
X char ident[ident_sz+1];
X
X /* ---------------------------------------------------------------- */
X /* open the module and try to test whatever is available */
X /* ---------------------------------------------------------------- */
X
X md_mod_open ();
X
X md_list_init (&s);
X while (md_list_next (&s, ident) == err_ok)
X {
X printf ("%-8s : ", ident);
X
X for (c = 0; testable_mds[c].ident != NULL &&
X strcasecmp(ident, testable_mds[c].ident) != 0; c++)
X ;
X
X if (testable_mds[c].ident == NULL)
X {
X printf ("no test suite exists.\n");
X continue;
X }
X
X /* ------------------------------------------------------------ */
X /* create an association for that particular message digest */
X /* ------------------------------------------------------------ */
X
X if (md_open (&ctx, ident) != err_ok)
X {
X printf ("internal error.\n");
X exit (1);
X }
X
X /* ------------------------------------------------------------ */
X /* call it, and then close the association */
X /* ------------------------------------------------------------ */
X
X c = (*(testable_mds[c].test))(&ctx);
X
X if (c == -1)
X printf ("test(s) failed !\n");
X else
X printf ("%d test%s, all successfull.\n", c, (c == 1) ?"":"s");
X
X md_close (&ctx);
X
X }
X
X exit (0);
X}
X
X
X/* -------------------------------------------------------------------- */
X/* function : digest_to_hex */
X/* description : format a digest into a hex string */
X/* -------------------------------------------------------------------- */
Xstatic string
Xdigest_to_hex (digest, sz)
X opaque digest; /* bytes of digest */
X word sz; /* # bytes in digest */
X{
X static char hex_str[81];
X word c;
X
X for (c = 0; c < sz; c++)
X sprintf (&hex_str[c<<1], "%02x", (digest[c] & 0xff));
X
X hex_str[c<<1] = '\0';
X return (hex_str);
X}
X
X/* -------------------------------------------------------------------- */
X/* -------------------------------------------------------------------- */
X/* place test routines/structures/info from here onwards ... */
X/* -------------------------------------------------------------------- */
X/* -------------------------------------------------------------------- */
X
Xtypedef struct
X {
X string test;
X string result;
X } test_set;
X
Xchar digest[64];
Xstring hdigest;
X
X/* -------------------------------------------------------------------- */
X/* function : check_test_set */
X/* description : check all items in a test_set */
X/* -------------------------------------------------------------------- */
XSTATIC word
Xcheck_test_set (ctx, tset)
X md_ctx* ctx;
X test_set tset[];
X{
X word c;
X
X for (c = 0; tset[c].test != NULL; c++)
X {
X md_init (ctx);
X md_update (ctx, tset[c].test, strlen(tset[c].test));
X md_final (ctx, digest);
X
X hdigest = digest_to_hex (digest, md_hash_sz (ctx));
X
X if (strcmp (hdigest, tset[c].result) != 0)
X return -1;
X }
X
X return c;
X}
X
X
X/* -------------------------------------------------------------------- */
X/* message-digest 4 test suite from RFC-1186 */
X/* -------------------------------------------------------------------- */
X
Xstatic test_set md4_tests[] =
X {
X { "",
X "31d6cfe0d16ae931b73c59d7e0c089c0" },
X { "a",
X "bde52cb31de33e46245e05fbdbd6fb24" },
X { "abc",
X "a448017aaf21d8525fc10ae87aa6729d" },
X { "message digest",
X "d9130a8164549fe818874806e1c7014b" },
X { "abcdefghijklmnopqrstuvwxyz",
X "d79e1c308aa5bbcdeea8ed63df412da9" },
X { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
X "043f8582f241db351ce627e153e7f0e4" },
X { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
X "e33b4ddc9c38f2199c3e7b164fcc0536" },
X { NULL,
X NULL },
X };
X
X/* -------------------------------------------------------------------- */
X/* function : test_md4 */
X/* description : run through the md4 test suite */
X/* -------------------------------------------------------------------- */
XSTATIC word
Xtest_md4 (ctx)
X md_ctx* ctx;
X{
X return check_test_set (ctx, md4_tests);
X}
X
X
X/* -------------------------------------------------------------------- */
X/* message-digest 5 test suite from RFC-1321 */
X/* -------------------------------------------------------------------- */
X
Xstatic test_set md5_tests[] =
X {
X { "",
X "d41d8cd98f00b204e9800998ecf8427e" },
X { "a",
X "0cc175b9c0f1b6a831c399e269772661" },
X { "abc",
X "900150983cd24fb0d6963f7d28e17f72" },
X { "message digest",
X "f96b697d7cb7938d525a2f31aaf161d0" },
X { "abcdefghijklmnopqrstuvwxyz",
X "c3fcd3d76192e4007dfb496cca67e13b" },
X { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
X "d174ab98d277d9f5a5611c2c9f419d9f" },
X { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
X "57edf4a22be3c955ac49da2e2107b67a" },
X { NULL,
X NULL },
X };
X
X/* -------------------------------------------------------------------- */
X/* function : test_md5 */
X/* description : run through the md5 test suite */
X/* -------------------------------------------------------------------- */
XSTATIC word
Xtest_md5 (ctx)
X md_ctx* ctx;
X{
X return check_test_set (ctx, md5_tests);
X}
X
X
X/* -------------------------------------------------------------------- */
X/* NIST shs test */
X/* -------------------------------------------------------------------- */
X
Xstatic test_set shs_tests[] =
X {
X { "abc",
X "0164b8a914cd2a5e74c4f7ff082c4d97f1edf880" },
X { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
X "d2516ee1acfa5baf33dfc1c471e438449ef134c8" },
X { NULL,
X NULL },
X };
X
X/* -------------------------------------------------------------------- */
X/* function : test_shs */
X/* description : go through NIST shs tests */
X/* -------------------------------------------------------------------- */
XSTATIC word
Xtest_shs (ctx)
X md_ctx* ctx;
X{
X word c;
X word i;
X char buf[1000];
X
X c = check_test_set (ctx, shs_tests);
X
X if (c == -1)
X return -1;
X
X /* ---------------------------------------------------------------- */
X /* do 1million 'a's. */
X /* ---------------------------------------------------------------- */
X
X memset (buf, 'a', 1000);
X
X md_init (ctx);
X for (i = 0; i < 1000; i++)
X md_update (ctx, buf, 1000);
X md_final (ctx, digest);
X
X hdigest = digest_to_hex (digest, md_hash_sz (ctx));
X
X if (strcmp (hdigest, "3232affa48628a26653b5aaa44541fd90d690603") != 0)
X return -1;
X
X return ++c;
X}
X
X
X/* -------------------------------------------------------------------- */
X/* function : test_haval */
X/* description : do haval test */
X/* -- NOTE -- : this assumes the default pass3=,fptlen=128/160 setup! */
X/* -------------------------------------------------------------------- */
XSTATIC word
Xtest_haval (ctx)
X md_ctx* ctx;
X{
X string test_f128 = "";
X string result_f128 = "1bdc556b29ad02ec09af8c66477f2a87";
X string test_f160 = "a";
X string result_f160 = "5e1610fced1d3adb0bb18e92ac2b11f0bd99d8ed";
X string t, r;
X
X
X if (md_hash_sz (ctx) == (128>>3))
X {
X t = test_f128;
X r = result_f128;
X }
X else if (md_hash_sz (ctx) == (160>>3))
X {
X t = test_f160;
X r = result_f160;
X }
X else
X return -1;
X
X md_init (ctx);
X md_update (ctx, t, strlen (t));
X md_final (ctx, digest);
X
X hdigest = digest_to_hex (digest, md_hash_sz (ctx));
X
X if (strcmp (hdigest, r) != 0)
X return -1;
X
X return 1;
X}
X
X/* -------------------------------------------------------------------- */
X
X
END_OF_FILE
if test 11052 -ne `wc -c <'mtest.c'`; then
echo shar: \"'mtest.c'\" unpacked with wrong size!
fi
# end of 'mtest.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 archives.
rm -f ark[1-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...