/* shs1.c librock_CHISEL _summary implements NIST Secure Hash Standard-1 (SHS1) also known as SHA1 */ #ifdef librock_NOTLIBROCK /**************************************************************/ /* ABOUT THIS FILE: GUIDE TO QUICK REUSE WITHOUT REWORK This file uses many preprocessor conditional blocks and features to publish http://www.mibsoftware.com/librock/ You can disable those features with little or no editing, and reuse this file: 1. At compile time, enable this conditional block by defining the preprocessor symbol librock_NOTLIBROCK, either with a compiler command line parameter, or as a #define in a source file which then #includes this source file. 2. Define any preprocessor symbols in this block (if any) appropriately for your machine and compilation environment. 3. Copy and use the declarations from this block in your source files as appropriate. This file is originally from the librock library, which is Free (libre), free (no cost), rock-stable API, and works on gcc/MSVC/Windows/Linux/BSD/more. Get originals, updates, license certificates, more, at http://www.mibsoftware.com/librock/ (Change log appears at end of this file.) */ #undef librock_ISOLATED #define librock_PRIVATE #define librock_uint16_t unsigned short #define librock_uint32_t unsigned long #define librock_PTR #define librock_CONST const typedef struct { librock_uint32_t digest[/*SHS1_DIGESTWORDS*/((20)/sizeof(librock_uint32_t))]; /* message digest */ librock_uint32_t countLo; /* 64 bit count: bits 3-34 */ librock_uint32_t countHi; /* 64 bit count: bits 35-63 */ librock_uint32_t datalen; /* length of data in data */ librock_uint32_t data[/*SHS1_CHUNKWORDS*/((1<<6)/sizeof(librock_uint32_t))]; /* SHS1 chunk buffer */ } librock_SHS1_INFO; /**************************************************************/ #endif #ifndef librock_ISOLATED /**************************************************************/ #define librock_IMPLEMENT_shs1 #ifndef librock_NOTLIBROCK #include #include #endif #define SHS1_INFO librock_SHS1_INFO #define shs1Init librock_shs1_Init #define shs1Update librock_shs1_Update #define shs1fullUpdate librock_shs1_fullUpdate #define shs1Final librock_shs1_Final void librock_shs1_fullUpdate (librock_SHS1_INFO*, const unsigned char *, librock_uint32_t);; #define BYTE_ORDER *((int *)byte_order_test) #define LITTLE_ENDIAN 1 #define BIG_ENDIAN 0x1000000 librock_PRIVATE const char byte_order_test[] = { 1, 0, 0, 0 }; /**************************************************************/ #endif #ifdef librock_IMPL_LIDESC #ifndef librock_NOIMPL_LIDESC_shs1 /* License description features are documented at http://www.mibsoftware.com/librock/ */ /**************************************************************/ #include /* librock_LIDESC_HC=1f75fc583e8442e328be6bd98ec63beef9389f4e */ void *librock_LIDESC_shs1[] = { "\n" __FILE__ librock_LIDESC_public "\n", 0 }; /**************************************************************/ #endif #endif #ifndef librock_WRAP /* Function wrapping and tracing features are documented at http://www.mibsoftware.com/librock/ */ /**************************************************************/ /**************************************************************/ #endif /* @(#)shs1.c 12.2 23 Nov 1995 01:15:43 */ /* * shs1 - implements new NIST Secure Hash Standard-1 (SHS1) * * Written 2 September 1992, Peter C. Gutmann. * * This file was Modified/Re-written by: * * Landon Curt Noll (chongo@toad.com) chongo /\../\ * * This code has been placed in the public domain. Please do not * copyright this code. * * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MER- * CHANTABILITY AND FITNESS. IN NO EVENT SHALL LANDON CURT * NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * See shs1drvr.c for version and modification history. */ /* librock_COMMENT: the comments in shs1drvr.c were copied here on 2002-04-18. The comments indicate that this is a branch from Peter Guttman's 1992 code, even though the 1994 version was also committed to librock CVS. The librock CVS log is at the end. * * * NOTE: The version information below refers to all shs1 code, not * just this file. In particular, this file was created by * Landon Curt Noll. * * Version 1.1: 02 Sep 1992? original authors * This code is based on code by Peter C. Gutmann. Much thanks goes * to Peter C. Gutman (pgut1@cs.aukuni.ac.nz) , Shawn A. Clifford * (sac@eng.ufl.edu), Pat Myrto (pat@rwing.uucp) and others who wrote * and/or worked on the original code. * * Version 2.1: 31 Dec 1993 Landon Curt Noll (chongo@toad.com) * Reformatted, performance improvements and bug fixes * * Version 2.2: 02 Jan 1994 Landon Curt Noll (chongo@toad.com) * fixed -p usage * better error messages * added -c help * added -c 0 (concatenation) * reordered -i stat buffer pre-pending * * Version 2.3: 03 Jan 1994 Landon Curt Noll (chongo@toad.com) * added -c 1 (side by side) * added -c 2 (even force to be odd) * added -c x (shs1 dual test suite) * changed -c help to be -c h * changed -c operand to type[,opt[,...]] * prefix & string ABI now can take arbitrary binary data * fixed memory leak * fixed even/odd byte split bug * added -P file * added -q * added UNROLL_LOOPS to control shs1.c loop unrolling * major performance improvements * * Version 2.4: 05 Jan 1994 Landon Curt Noll (chongo@toad.com) * renamed calc mode to dual mode * removed all -c code * added -d (dual digests, space separated) * rewrote most of the file, string and stream logic using shs1dual code * * Version 2.5: 08 Jan 1994 Landon Curt Noll (chongo@toad.com) * added (new) -c (print 0x in front of digests) * removed st_blksize and st_blocks from -i preprocessing data * only print .0 suffix if -i and digesting a file * non-zero edit codes are now unique * changed the dual test suite (shorter, added non alpha numeric chars) * -i requires filenames * fixed @(#) what string code * boolean logic simplication by Rich Schroeppel (rcs@cs.arizona.edu) * on the fly in a circular buffer by Colin Plumb (colin@nyx10.cs.du.edu) * * Version 2.6: 11 Jan 1994 Landon Curt Noll (chongo@toad.com) * Merged the shs1 and md5 Makefiles to build both in the same directory * alignment and byte order performance improvements * eliminate wateful memory copies * shs1 transform contains no function calls * beta release * * Version 2.7: 13 Jan 1994 Landon Curt Noll (chongo@toad.com) * code cleanup * chunk is now 64 bytes, block is determined by blocking factor * magic 64 and 64 related values defined in terms of #defines * added blocking code (-b block_len) * added xor feedback code (-f) * added xor feedback and block options to performance test * performance improvements * * Version 2.8: 16 Jan 1994 Landon Curt Noll (chongo@toad.com) * code cleanup * performance improvements * removed blocking and feedback code * count bytes in driver, convert to 64 bit count in final transform * added debug mode * handle read errors and EOF better * prefix strings not multiple of 64 bytes in length do not slow down hash * renumbered exit codes * fixed dual digest split bug * byte sex swapping is now controlled thru the SHS1_TRANSFORM macro * shs1Transform() is now called via the SHS1_TRANSFORM macro * * Version 2.9: 12 Feb 1994 Landon Curt Noll (chongo@toad.com) * prep for beta release * removed all feedback code * * Version 2.10: 25 Mar 1994 Landon Curt Noll (chongo@toad.com) * must_align catchs signal to detect misaligned access * * Version 3.1: 09 Mar 1995 Landon Curt Noll (chongo@toad.com) * Changed to implement the new Secure Hash Standard-1 (SHS1). * The Secure Hash Standard-1 (SHS1) is a United States Department * of Commerce National Institute of Standards and Technology approved * standard (FIPS Pub 180-1). * * The only substantial change was made to the exor() macro in shs1.c * Changed name to shs1. Bumped version from 2.10 to 3.1. * * Moved stream and file routines into shs1io.c. * * Version 3.2: 17 Nov 1995 Landon Curt Noll (chongo@toad.com) * Fixed help string. * * Added multiple digests capability instead of just dual. Added * -m num to denote 2 or more multiple digests. * * Added -C to prevent spaces (and later 0x if -c) between multi digests. * * Version 3.3: 01 Sep 1996 Landon Curt Noll (chongo@toad.com) * Provide sha1 as well as shs1. */ #include #include #define SHS1_IO /* #include "shs1.h" Inlined. 2002-04-18 forrest@mibsoftware.com /* * Useful defines/typedefs */ typedef unsigned char BYTE; /* must be a 1 byte unsigned value */ typedef librock_uint16_t UINT; /* must be a 2 byte unsigned value */ typedef librock_uint32_t ULONG; /* must be a 4 byte unsigned value */ # define P(a) a /* SHS1_CHUNKSIZE must be a power of 2 - fixed value defined by the algorithm */ #define SHS1_CHUNKSIZE (1<<6) #define SHS1_CHUNKWORDS (SHS1_CHUNKSIZE/sizeof(ULONG)) /* SHS1_DIGESTSIZE is a the length of the digest as defined by the algorithm */ #define SHS1_DIGESTSIZE (20) #define SHS1_DIGESTWORDS (SHS1_DIGESTSIZE/sizeof(ULONG)) /* SHS1_LOW - where low 32 bits of 64 bit count is stored during final */ #define SHS1_LOW 15 /* SHS1_HIGH - where high 32 bits of 64 bit count is stored during final */ #define SHS1_HIGH 14 /* SHS1_BLOCKSIZE is how large a chunk multiStream processes at a time */ #define SHS1_BLOCKSIZE (SHS1_CHUNKSIZE<<8) /* SHS1_READSIZE must be a multiple of SHS1_BLOCKSIZE */ #define SHS1_READSIZE (SHS1_BLOCKSIZE<<2) #define SHS1_READWORDS (SHS1_READSIZE/sizeof(ULONG)) /* maximum part of pre_file used */ #define SHS1_MAX_PRE_FILE 32768 /* * SHS1_SWAP_BYTE_SEX(ULONG *dest, ULONG *src) * * dest - array of SHS1_CHUNKWORDS ULONG of fixed data (may be src) * src - array of SHS1_CHUNKWORDS ULONG of what to fix * * This macro will either switch to the opposite byte sex (Big Endian vs. * Little Endian). */ #define SHS1_SWAP_BYTE_SEX(dest, src) { /* swap byte sex if needed */ \ int tmp_i; /* index */ \ for (tmp_i=0; tmp_i < SHS1_CHUNKWORDS; ++tmp_i) { \ ((ULONG*)(dest))[tmp_i] = \ (((ULONG*)(src))[tmp_i] << 16) | \ (((ULONG*)(src))[tmp_i] >> 16); \ ((ULONG*)(dest))[tmp_i] = \ ((((ULONG*)(dest))[tmp_i] & 0xff00ff00UL) >> 8) | \ ((((ULONG*)(dest))[tmp_i] & 0x00ff00ffUL) << 8); \ } \ } /* * SHS1_ROUNDUP(x,y) - round x up to the next multiple of y */ #define SHS1_ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) /* * SHS1_TRANSFORM(SHS1_INFO *a, ULONG *b, ULONG *c) * * a pointer to our current digest state * b pointer to SHS1_CHUNKSIZE words of byte sex fixed data * c pointer to SHS1_CHUNKSIZE words that do not need to be fixed */ /* Rewrote to let the compiler figure and optimize it out */ # define SHS1_TRANSFORM(a,b,c) \ if (BYTE_ORDER == BIG_ENDIAN) \ shs1Transform(((SHS1_INFO *)(a))->digest, (ULONG *)(c)); \ else { \ SHS1_SWAP_BYTE_SEX((b), (c)); \ shs1Transform(((SHS1_INFO *)(a))->digest, (ULONG *)(b)); \ } /* * SHS1COUNT(SHS1_INFO*, ULONG) - update the 64 bit count in an SHS1_INFO * * We will count bytes and convert to bit count during the final * transform. */ #define SHS1COUNT(shs1info, count) { \ ULONG tmp_countLo; \ tmp_countLo = (shs1info)->countLo; \ if (((shs1info)->countLo += (count)) < tmp_countLo) { \ (shs1info)->countHi++; \ } \ } /* #include "align.h" not for librock */ /* #include "endian.h" not for librock */ /* Not for librock char *shs1_what="@(#)";*/ /* #(@) if checked in */ /* * The SHS1 f()-functions. The f1 and f3 functions can be optimized * to save one boolean operation each - thanks to Rich Schroeppel, * rcs@cs.arizona.edu for discovering this. * * f1: ((x&y) | (~x&z)) == (z ^ (x&(y^z))) * f3: ((x&y) | (x&z) | (y&z)) == ((x&y) | (z&(x|y))) */ #define f1(x,y,z) (z ^ (x&(y^z))) /* Rounds 0-19 */ #define f2(x,y,z) (x^y^z) /* Rounds 20-39 */ #define f3(x,y,z) ((x&y) | (z&(x|y))) /* Rounds 40-59 */ #define f4(x,y,z) (x^y^z) /* Rounds 60-79 */ /* The SHS1 Mysterious Constants */ #define K1 0x5A827999L /* Rounds 0-19 */ #define K2 0x6ED9EBA1L /* Rounds 20-39 */ #define K3 0x8F1BBCDCL /* Rounds 40-59 */ #define K4 0xCA62C1D6L /* Rounds 60-79 */ /* SHS1 initial values */ #define h0init 0x67452301L #define h1init 0xEFCDAB89L #define h2init 0x98BADCFEL #define h3init 0x10325476L #define h4init 0xC3D2E1F0L /* 32-bit rotate left - kludged with shifts */ #define LEFT_ROT(X,n) (((X)<<(n)) | ((X)>>(32-(n)))) /* * * The initial expanding function. The hash function is defined over an * 80-word expanded input array W, where the first 16 are copies of the input * data, and the remaining 64 are defined by * * W[i] = LEFT_ROT(W[i-16] ^ W[i-14] ^ W[i-8] ^ W[i-3], 1) * * NOTE: The expanding function used in rounds 16 to 79 was changed from the * original SHA (in FIPS Pub 180) to one that also left circular shifted * by one bit for Secure Hash Algorithm-1 (FIPS Pub 180-1). */ #define exor(W,i,t) \ (t = (W[i&15] ^ W[(i-14)&15] ^ W[(i-8)&15] ^ W[(i-3)&15]), \ W[i&15] = LEFT_ROT(t, 1)) /* * The prototype SHS1 sub-round. The fundamental sub-round is: * * a' = e + LEFT_ROT(a,5) + f(b,c,d) + k + data; * b' = a; * c' = LEFT_ROT(b,30); * d' = c; * e' = d; * * but this is implemented by unrolling the loop 5 times and renaming the * variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. * This code is then replicated 20 times for each of the 4 functions, using * the next 20 values from the W[] array each time. */ #define subRound(a, b, c, d, e, f, k, data) \ (e += LEFT_ROT(a,5) + f(b,c,d) + k + data, b = LEFT_ROT(b,30)) /* forward declarations */ static void shs1Transform P((ULONG*, ULONG*)); /* librock: removed global static. static ULONG in[SHS1_CHUNKWORDS]; */ #ifdef librock_MANUAL_shs1 /* librock_shs1 - NIST Secure Hash Standard-1 (SHS1) also known as SHA1 */ /**/ #include #include void librock_shs1_Init (librock_SHS1_INFO *pinfo); void librock_shs1_Update (librock_SHS1_INFO *pinfo, const unsigned char *buffer, librock_uint32_t len); void librock_shs1_Final (librock_SHS1_INFO*); /* This is the NIST Secure Hash Standard-1 (SHS1) also known as SHA1. This comes from Landon Curt Noll's md5_rsa hash package with some changes for librock: The names in the file were changed to use the librock_ prefix. The necessary definitions from the include files were incorporated. ENDIAN-ness tests are modified. SHS1COUNT() is called by us, not the caller. Removed a global static variable, for MT-safety. To compute the SHA1 Message-Digest, declare a librock_SHS1_INFO (a typedef'ed structure) which is initialized with a call to librock_shs1_Init(). After making one or more calls to librock_shs1_Update(), call librock_shs1_Final() to place the result into the digest member of the librock_SHS1_INFO. To show this buffer as ASCII, use code similar to the example below. The well-known algorithm is described elsewhere The design property that is that the result is unique for unique input, and it is computationally infeasible to create text with a given result. Secure hashes (also known as message digests) are used as a unique "fingerprint" (which can verify the integrity of a file or character sequence without a byte by byte comparison.) They are also used as unique hash values. (The computational load to compute this result is significant compared to CRC32, so it should be used only when the uniqueness of the result for unique input is essential, or protecting against generated input which matches a known result is required.) librock_shs1_Update() may save up to 64 bytes of a buffer in the librock_SHS1_INFO structure in between calls. That memory is zeroed on librock_shs1_Final. But callers may want to use care when working with input which must not be exposed. Typical use: */ #ifdef librock_TYPICAL_USE_shs1_Update #include #include char buf[8*5+1]; char *str = "This is a test string."; int len = strlen(str); librock_SHS1_INFO shsInfo; librock_shs1_Init( &shsInfo ); librock_shs1_Update( &shsInfo, ( unsigned char * ) str, len ); librock_shs1_Final( &shsInfo ); sprintf(buf,"%08lX%08lX%08lX%08lX%08lX",shsInfo.digest[0], shsInfo.digest[1],shsInfo.digest[2],shsInfo.digest[3],shsInfo.digest[4]); printf("%s\n",buf); #endif /* memset(), memcpy() // Well-behaved in multi-threaded uses. */ #endif /* MANUAL */ /* * shs1Init - initialize the SHS1 state */ void shs1Init(dig) SHS1_INFO *dig; { /* Set the h-vars to their initial values */ dig->digest[0] = h0init; dig->digest[1] = h1init; dig->digest[2] = h2init; dig->digest[3] = h3init; dig->digest[4] = h4init; /* Initialise bit count */ dig->countLo = 0; dig->countHi = 0; dig->datalen = 0; } /* * shs1Transform - perform the SHS1 transformatio * * Note that this code, like MD5, seems to break some optimizing compilers. * It may be necessary to split it into sections, eg based on the four * subrounds. One may also want to roll each subround into a loop. */ static void shs1Transform(digest, W) ULONG *digest; ULONG *W; { ULONG A, B, C, D, E; /* Local vars */ ULONG t; /* temp storage for exor() */ /* Set up first buffer and local data buffer */ A = digest[0]; B = digest[1]; C = digest[2]; D = digest[3]; E = digest[4]; /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ subRound(A, B, C, D, E, f1, K1, W[ 0]); subRound(E, A, B, C, D, f1, K1, W[ 1]); subRound(D, E, A, B, C, f1, K1, W[ 2]); subRound(C, D, E, A, B, f1, K1, W[ 3]); subRound(B, C, D, E, A, f1, K1, W[ 4]); subRound(A, B, C, D, E, f1, K1, W[ 5]); subRound(E, A, B, C, D, f1, K1, W[ 6]); subRound(D, E, A, B, C, f1, K1, W[ 7]); subRound(C, D, E, A, B, f1, K1, W[ 8]); subRound(B, C, D, E, A, f1, K1, W[ 9]); subRound(A, B, C, D, E, f1, K1, W[10]); subRound(E, A, B, C, D, f1, K1, W[11]); subRound(D, E, A, B, C, f1, K1, W[12]); subRound(C, D, E, A, B, f1, K1, W[13]); subRound(B, C, D, E, A, f1, K1, W[14]); subRound(A, B, C, D, E, f1, K1, W[15]); subRound(E, A, B, C, D, f1, K1, exor(W,16,t)); subRound(D, E, A, B, C, f1, K1, exor(W,17,t)); subRound(C, D, E, A, B, f1, K1, exor(W,18,t)); subRound(B, C, D, E, A, f1, K1, exor(W,19,t)); subRound(A, B, C, D, E, f2, K2, exor(W,20,t)); subRound(E, A, B, C, D, f2, K2, exor(W,21,t)); subRound(D, E, A, B, C, f2, K2, exor(W,22,t)); subRound(C, D, E, A, B, f2, K2, exor(W,23,t)); subRound(B, C, D, E, A, f2, K2, exor(W,24,t)); subRound(A, B, C, D, E, f2, K2, exor(W,25,t)); subRound(E, A, B, C, D, f2, K2, exor(W,26,t)); subRound(D, E, A, B, C, f2, K2, exor(W,27,t)); subRound(C, D, E, A, B, f2, K2, exor(W,28,t)); subRound(B, C, D, E, A, f2, K2, exor(W,29,t)); subRound(A, B, C, D, E, f2, K2, exor(W,30,t)); subRound(E, A, B, C, D, f2, K2, exor(W,31,t)); subRound(D, E, A, B, C, f2, K2, exor(W,32,t)); subRound(C, D, E, A, B, f2, K2, exor(W,33,t)); subRound(B, C, D, E, A, f2, K2, exor(W,34,t)); subRound(A, B, C, D, E, f2, K2, exor(W,35,t)); subRound(E, A, B, C, D, f2, K2, exor(W,36,t)); subRound(D, E, A, B, C, f2, K2, exor(W,37,t)); subRound(C, D, E, A, B, f2, K2, exor(W,38,t)); subRound(B, C, D, E, A, f2, K2, exor(W,39,t)); subRound(A, B, C, D, E, f3, K3, exor(W,40,t)); subRound(E, A, B, C, D, f3, K3, exor(W,41,t)); subRound(D, E, A, B, C, f3, K3, exor(W,42,t)); subRound(C, D, E, A, B, f3, K3, exor(W,43,t)); subRound(B, C, D, E, A, f3, K3, exor(W,44,t)); subRound(A, B, C, D, E, f3, K3, exor(W,45,t)); subRound(E, A, B, C, D, f3, K3, exor(W,46,t)); subRound(D, E, A, B, C, f3, K3, exor(W,47,t)); subRound(C, D, E, A, B, f3, K3, exor(W,48,t)); subRound(B, C, D, E, A, f3, K3, exor(W,49,t)); subRound(A, B, C, D, E, f3, K3, exor(W,50,t)); subRound(E, A, B, C, D, f3, K3, exor(W,51,t)); subRound(D, E, A, B, C, f3, K3, exor(W,52,t)); subRound(C, D, E, A, B, f3, K3, exor(W,53,t)); subRound(B, C, D, E, A, f3, K3, exor(W,54,t)); subRound(A, B, C, D, E, f3, K3, exor(W,55,t)); subRound(E, A, B, C, D, f3, K3, exor(W,56,t)); subRound(D, E, A, B, C, f3, K3, exor(W,57,t)); subRound(C, D, E, A, B, f3, K3, exor(W,58,t)); subRound(B, C, D, E, A, f3, K3, exor(W,59,t)); subRound(A, B, C, D, E, f4, K4, exor(W,60,t)); subRound(E, A, B, C, D, f4, K4, exor(W,61,t)); subRound(D, E, A, B, C, f4, K4, exor(W,62,t)); subRound(C, D, E, A, B, f4, K4, exor(W,63,t)); subRound(B, C, D, E, A, f4, K4, exor(W,64,t)); subRound(A, B, C, D, E, f4, K4, exor(W,65,t)); subRound(E, A, B, C, D, f4, K4, exor(W,66,t)); subRound(D, E, A, B, C, f4, K4, exor(W,67,t)); subRound(C, D, E, A, B, f4, K4, exor(W,68,t)); subRound(B, C, D, E, A, f4, K4, exor(W,69,t)); subRound(A, B, C, D, E, f4, K4, exor(W,70,t)); subRound(E, A, B, C, D, f4, K4, exor(W,71,t)); subRound(D, E, A, B, C, f4, K4, exor(W,72,t)); subRound(C, D, E, A, B, f4, K4, exor(W,73,t)); subRound(B, C, D, E, A, f4, K4, exor(W,74,t)); subRound(A, B, C, D, E, f4, K4, exor(W,75,t)); subRound(E, A, B, C, D, f4, K4, exor(W,76,t)); subRound(D, E, A, B, C, f4, K4, exor(W,77,t)); subRound(C, D, E, A, B, f4, K4, exor(W,78,t)); subRound(B, C, D, E, A, f4, K4, exor(W,79,t)); /* Build message digest */ digest[0] += A; digest[1] += B; digest[2] += C; digest[3] += D; digest[4] += E; } /* * shs1Update - update SHS1 with arbitrary length data * * This code does not assume that the buffer size is a multiple of * SHS1_CHUNKSIZE bytes long. This code handles partial chunk between * calls to shs1Update(). */ void shs1Update( SHS1_INFO *dig, const BYTE *buffer, ULONG count) { ULONG datalen = dig->datalen; SHS1COUNT(dig,count); /* Line added For librock */ /* * Catch the case of a non-empty data buffer */ if (datalen > 0) { /* determine the size we need to copy */ ULONG cpylen = SHS1_CHUNKSIZE - datalen; /* case: new data will not fill the buffer */ if (cpylen > count) { memcpy((char *)dig->data+datalen, (char *)buffer, count); dig->datalen = datalen+count; return; /* case: buffer will be filled */ } else { ULONG in[SHS1_CHUNKWORDS]; memcpy((char *)dig->data+datalen, (char *)buffer, cpylen); SHS1_TRANSFORM(dig, in, dig->data); buffer += cpylen; count -= cpylen; dig->datalen = 0; } } /* * Process data in SHS1_CHUNKSIZE chunks */ if (count >= SHS1_CHUNKSIZE) { shs1fullUpdate(dig, buffer, count); buffer += (count/SHS1_CHUNKSIZE)*SHS1_CHUNKSIZE; count %= SHS1_CHUNKSIZE; } /* * Handle any remaining bytes of data. * This should only happen once on the final lot of data */ if (count > 0) { memcpy((char *)dig->data, (char *)buffer, count); } dig->datalen = count; } /* * shs1fullUpdate - update SHS1 with chunk multiple length data * * This function assumes that count is a multiple of SHS1_CHUNKSIZE and that * no partial chunk is left over from a previous call. */ void shs1fullUpdate( SHS1_INFO *dig, const BYTE *buffer, ULONG count) { ULONG in[SHS1_CHUNKWORDS]; /* For librock MT-safety */ /* * Process data in SHS1_CHUNKSIZE chunks */ while (count >= SHS1_CHUNKSIZE) { #if defined(MUST_ALIGN) if ((long)buffer & (sizeof(ULONG)-1)) { memcpy((char *)in, (char *)buffer, SHS1_CHUNKSIZE); SHS1_TRANSFORM(dig, in, in); } else { SHS1_TRANSFORM(dig, in, buffer); } #else SHS1_TRANSFORM(dig, in, buffer); #endif buffer += SHS1_CHUNKSIZE; count -= SHS1_CHUNKSIZE; } } /* * shs1Final - perform final SHS1 transforms * * At this point we have less than a full chunk of data remaining * (and possibly no data) in the shs1 state data buffer. * * First we append a final 0x80 byte. * * Next if we have more than 56 bytes, we will zero fill the remainder * of the chunk, transform and then zero fill the first 56 bytes. * If we have 56 or fewer bytes, we will zero fill out to the 56th * chunk byte. Regardless, we wind up with 56 bytes data. * * Finally we append the 64 bit length on to the 56 bytes of data * remaining. This final chunk is transformed. */ void shs1Final(dig) SHS1_INFO *dig; { int count = dig->datalen; ULONG lowBitcount = dig->countLo; ULONG highBitcount = dig->countHi; /* * Set the first char of padding to 0x80. * This is safe since there is always at least one byte free */ ((BYTE *)dig->data)[count++] = 0x80; /* Pad out to 56 mod SHS1_CHUNKSIZE */ if (count > 56) { /* Two lots of padding: Pad the first chunk to SHS1_CHUNKSIZE bytes */ memset((BYTE *)dig->data + count, 0, SHS1_CHUNKSIZE - count); SHS1_TRANSFORM(dig, dig->data, dig->data); /* Now fill the next chunk with 56 bytes */ memset(dig->data, 0, 56); } else { /* Pad chunk to 56 bytes */ memset((BYTE *)dig->data + count, 0, 56 - count); } /* For librock: Rewrote to be a test in code, not compile-time macros */ if (BYTE_ORDER == LITTLE_ENDIAN) { SHS1_SWAP_BYTE_SEX(dig->data, dig->data); } /* * Append length in bits and transform * * We assume that bit count is a multiple of 8 because we have * only processed full bytes. */ dig->data[SHS1_HIGH] = (highBitcount << 3) | (lowBitcount >> 29); dig->data[SHS1_LOW] = (lowBitcount << 3); shs1Transform(dig->digest, dig->data); dig->datalen = 0; memset(dig->data, 0, sizeof(dig->data)); /* For librock. Make sure any saved state is clear. */ } /* $Log: shs1.c,v $ Revision 1.7 2002/08/01 22:02:41 forrest@mibsoftware.com rights=#1 Updated TYPICAL_USE section. Added NOTLIBROCK section. Moved CVS log to end. Changed LIDESC MD5 to HC. Revision 1.6 2002/04/19 14:48:53 forrest@mibsoftware.com rights=#1 Finish import and fixes for librock. Revision 1.5 2002/04/19 04:08:04 forrest@mibsoftware.com rights=#1 librock_ACQUIRED 2002-04-18 http://www.isthe.com/chongo/src/md5_sha/md5_sha.tar.gz http://www.isthe.com/chongo/tech/comp/ Landon Curt Noll's set of changes. This is hash/shs1.c from that package. Revision 1.4 2002/04/19 04:00:38 forrest@mibsoftware.com rights=#1 Update to SHA-1. Message-Id: <30ajo5$oe8@ccu2.auckland.ac.nz> From: Peter Gutmann (pgut1@cs.aukuni.ac.nz) Newsgroups: sci.crypt Date: 1994-07-17 11:03:35 PST Revision 1.3 2002/04/19 03:53:12 forrest@mibsoftware.com rights=#1 Initial commit. Some librock features. NOTE: This is the "old" shs, not shs1. Written 2 September 1992 librock_ACQUIRED 2002-04-18 http://groups.google.com/groups?selm=1992Sep4.060230.28313%40cs.aukuni.ac.nz&output=gplain rights#1 Written by Peter C. Gutmann. Placed into the public domain in rights#1 Usenet message Message-ID: <1992Sep4.060230.28313@cs.aukuni.ac.nz> rights#1 From: Peter Gutmann (pgut1@cs.aukuni.ac.nz) rights#1 Date: Fri, 4 Sep 1992 06:02:30 GMT rights#1 Newsgroups: sci.crypt rights#1 License text in librock_LIDESC_HC=1f75fc583e8442e328be6bd98ec63beef9389f4e */