|  | /* crypto/md32_common.h */ | 
|  | /* ==================================================================== | 
|  | * Copyright (c) 1999 The OpenSSL Project.  All rights reserved. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions | 
|  | * are met: | 
|  | * | 
|  | * 1. Redistributions of source code must retain the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer. | 
|  | * | 
|  | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer in | 
|  | *    the documentation and/or other materials provided with the | 
|  | *    distribution. | 
|  | * | 
|  | * 3. All advertising materials mentioning features or use of this | 
|  | *    software must display the following acknowledgment: | 
|  | *    "This product includes software developed by the OpenSSL Project | 
|  | *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | 
|  | * | 
|  | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | 
|  | *    endorse or promote products derived from this software without | 
|  | *    prior written permission. For written permission, please contact | 
|  | *    licensing@OpenSSL.org. | 
|  | * | 
|  | * 5. Products derived from this software may not be called "OpenSSL" | 
|  | *    nor may "OpenSSL" appear in their names without prior written | 
|  | *    permission of the OpenSSL Project. | 
|  | * | 
|  | * 6. Redistributions of any form whatsoever must retain the following | 
|  | *    acknowledgment: | 
|  | *    "This product includes software developed by the OpenSSL Project | 
|  | *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | 
|  | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|  | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
|  | * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR | 
|  | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
|  | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
|  | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
|  | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
|  | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 
|  | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
|  | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 
|  | * OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | * ==================================================================== | 
|  | * | 
|  | * This product includes cryptographic software written by Eric Young | 
|  | * (eay@cryptsoft.com).  This product includes software written by Tim | 
|  | * Hudson (tjh@cryptsoft.com). | 
|  | * | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * This is a generic 32 bit "collector" for message digest algorithms. | 
|  | * Whenever needed it collects input character stream into chunks of | 
|  | * 32 bit values and invokes a block function that performs actual hash | 
|  | * calculations. | 
|  | * | 
|  | * Porting guide. | 
|  | * | 
|  | * Obligatory macros: | 
|  | * | 
|  | * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN | 
|  | *	this macro defines byte order of input stream. | 
|  | * HASH_CBLOCK | 
|  | *	size of a unit chunk HASH_BLOCK operates on. | 
|  | * HASH_LONG | 
|  | *	has to be at lest 32 bit wide, if it's wider, then | 
|  | *	HASH_LONG_LOG2 *has to* be defined along | 
|  | * HASH_CTX | 
|  | *	context structure that at least contains following | 
|  | *	members: | 
|  | *		typedef struct { | 
|  | *			... | 
|  | *			HASH_LONG	Nl,Nh; | 
|  | *			HASH_LONG	data[HASH_LBLOCK]; | 
|  | *			int		num; | 
|  | *			... | 
|  | *			} HASH_CTX; | 
|  | * HASH_UPDATE | 
|  | *	name of "Update" function, implemented here. | 
|  | * HASH_TRANSFORM | 
|  | *	name of "Transform" function, implemented here. | 
|  | * HASH_FINAL | 
|  | *	name of "Final" function, implemented here. | 
|  | * HASH_BLOCK_HOST_ORDER | 
|  | *	name of "block" function treating *aligned* input message | 
|  | *	in host byte order, implemented externally. | 
|  | * HASH_BLOCK_DATA_ORDER | 
|  | *	name of "block" function treating *unaligned* input message | 
|  | *	in original (data) byte order, implemented externally (it | 
|  | *	actually is optional if data and host are of the same | 
|  | *	"endianess"). | 
|  | * HASH_MAKE_STRING | 
|  | *	macro convering context variables to an ASCII hash string. | 
|  | * | 
|  | * Optional macros: | 
|  | * | 
|  | * B_ENDIAN or L_ENDIAN | 
|  | *	defines host byte-order. | 
|  | * HASH_LONG_LOG2 | 
|  | *	defaults to 2 if not states otherwise. | 
|  | * HASH_LBLOCK | 
|  | *	assumed to be HASH_CBLOCK/4 if not stated otherwise. | 
|  | * HASH_BLOCK_DATA_ORDER_ALIGNED | 
|  | *	alternative "block" function capable of treating | 
|  | *	aligned input message in original (data) order, | 
|  | *	implemented externally. | 
|  | * | 
|  | * MD5 example: | 
|  | * | 
|  | *	#define DATA_ORDER_IS_LITTLE_ENDIAN | 
|  | * | 
|  | *	#define HASH_LONG		MD5_LONG | 
|  | *	#define HASH_LONG_LOG2		MD5_LONG_LOG2 | 
|  | *	#define HASH_CTX		MD5_CTX | 
|  | *	#define HASH_CBLOCK		MD5_CBLOCK | 
|  | *	#define HASH_LBLOCK		MD5_LBLOCK | 
|  | *	#define HASH_UPDATE		MD5_Update | 
|  | *	#define HASH_TRANSFORM		MD5_Transform | 
|  | *	#define HASH_FINAL		MD5_Final | 
|  | *	#define HASH_BLOCK_HOST_ORDER	md5_block_host_order | 
|  | *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order | 
|  | * | 
|  | *					<appro@fy.chalmers.se> | 
|  | */ | 
|  |  | 
|  | #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) | 
|  | #error "DATA_ORDER must be defined!" | 
|  | #endif | 
|  |  | 
|  | #ifndef HASH_CBLOCK | 
|  | #error "HASH_CBLOCK must be defined!" | 
|  | #endif | 
|  | #ifndef HASH_LONG | 
|  | #error "HASH_LONG must be defined!" | 
|  | #endif | 
|  | #ifndef HASH_CTX | 
|  | #error "HASH_CTX must be defined!" | 
|  | #endif | 
|  |  | 
|  | #ifndef HASH_UPDATE | 
|  | #error "HASH_UPDATE must be defined!" | 
|  | #endif | 
|  | #ifndef HASH_TRANSFORM | 
|  | #error "HASH_TRANSFORM must be defined!" | 
|  | #endif | 
|  | #ifndef HASH_FINAL | 
|  | #error "HASH_FINAL must be defined!" | 
|  | #endif | 
|  |  | 
|  | #ifndef HASH_BLOCK_HOST_ORDER | 
|  | #error "HASH_BLOCK_HOST_ORDER must be defined!" | 
|  | #endif | 
|  |  | 
|  | #if 0 | 
|  | /* | 
|  | * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED | 
|  | * isn't defined. | 
|  | */ | 
|  | #ifndef HASH_BLOCK_DATA_ORDER | 
|  | #error "HASH_BLOCK_DATA_ORDER must be defined!" | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #ifndef HASH_LBLOCK | 
|  | #define HASH_LBLOCK	(HASH_CBLOCK/4) | 
|  | #endif | 
|  |  | 
|  | #ifndef HASH_LONG_LOG2 | 
|  | #define HASH_LONG_LOG2	2 | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * Engage compiler specific rotate intrinsic function if available. | 
|  | */ | 
|  | #undef ROTATE | 
|  | #ifndef PEDANTIC | 
|  | # if defined(_MSC_VER) | 
|  | #  define ROTATE(a,n)	_lrotl(a,n) | 
|  | # elif defined(__MWERKS__) | 
|  | #  define ROTATE(a,n)	__rol(a,n) | 
|  | # elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) | 
|  | /* | 
|  | * Some GNU C inline assembler templates. Note that these are | 
|  | * rotates by *constant* number of bits! But that's exactly | 
|  | * what we need here... | 
|  | * | 
|  | * 					<appro@fy.chalmers.se> | 
|  | */ | 
|  | #  if defined(__i386) | 
|  | #   define ROTATE(a,n)	({ register unsigned int ret;	\ | 
|  | asm volatile (		\ | 
|  | "roll %1,%0"		\ | 
|  | : "=r"(ret)		\ | 
|  | : "I"(n), "0"(a)	\ | 
|  | : "cc");		\ | 
|  | ret;				\ | 
|  | }) | 
|  | #  elif defined(__powerpc) | 
|  | #   define ROTATE(a,n)	({ register unsigned int ret;	\ | 
|  | asm volatile (		\ | 
|  | "rlwinm %0,%1,%2,0,31"	\ | 
|  | : "=r"(ret)		\ | 
|  | : "r"(a), "I"(n));	\ | 
|  | ret;				\ | 
|  | }) | 
|  | #  endif | 
|  | # endif | 
|  |  | 
|  | /* | 
|  | * Engage compiler specific "fetch in reverse byte order" | 
|  | * intrinsic function if available. | 
|  | */ | 
|  | # if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) | 
|  | /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */ | 
|  | #  if defined(__i386) && !defined(I386_ONLY) | 
|  | #   define BE_FETCH32(a)	({ register unsigned int l=(a);\ | 
|  | asm volatile (		\ | 
|  | "bswapl %0"		\ | 
|  | : "=r"(l) : "0"(l));	\ | 
|  | l;				\ | 
|  | }) | 
|  | #  elif defined(__powerpc) | 
|  | #   define LE_FETCH32(a)	({ register unsigned int l;	\ | 
|  | asm volatile (		\ | 
|  | "lwbrx %0,0,%1"		\ | 
|  | : "=r"(l)		\ | 
|  | : "r"(a));		\ | 
|  | l;				\ | 
|  | }) | 
|  |  | 
|  | #  elif defined(__sparc) && defined(ULTRASPARC) | 
|  | #  define LE_FETCH32(a)	({ register unsigned int l;		\ | 
|  | asm volatile (			\ | 
|  | "lda [%1]#ASI_PRIMARY_LITTLE,%0"\ | 
|  | : "=r"(l)			\ | 
|  | : "r"(a));			\ | 
|  | l;					\ | 
|  | }) | 
|  | #  endif | 
|  | # endif | 
|  | #endif /* PEDANTIC */ | 
|  |  | 
|  | #if HASH_LONG_LOG2==2	/* Engage only if sizeof(HASH_LONG)== 4 */ | 
|  | /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */ | 
|  | #ifdef ROTATE | 
|  | /* 5 instructions with rotate instruction, else 9 */ | 
|  | #define REVERSE_FETCH32(a,l)	(					\ | 
|  | l=*(const HASH_LONG *)(a),				\ | 
|  | ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24)))	\ | 
|  | ) | 
|  | #else | 
|  | /* 6 instructions with rotate instruction, else 8 */ | 
|  | #define REVERSE_FETCH32(a,l)	(				\ | 
|  | l=*(const HASH_LONG *)(a),			\ | 
|  | l=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)),	\ | 
|  | ROTATE(l,16)					\ | 
|  | ) | 
|  | /* | 
|  | * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|... | 
|  | * It's rewritten as above for two reasons: | 
|  | *	- RISCs aren't good at long constants and have to explicitely | 
|  | *	  compose 'em with several (well, usually 2) instructions in a | 
|  | *	  register before performing the actual operation and (as you | 
|  | *	  already realized:-) having same constant should inspire the | 
|  | *	  compiler to permanently allocate the only register for it; | 
|  | *	- most modern CPUs have two ALUs, but usually only one has | 
|  | *	  circuitry for shifts:-( this minor tweak inspires compiler | 
|  | *	  to schedule shift instructions in a better way... | 
|  | * | 
|  | *				<appro@fy.chalmers.se> | 
|  | */ | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #ifndef ROTATE | 
|  | #define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED | 
|  | * and HASH_BLOCK_HOST_ORDER ought to be the same if input data | 
|  | * and host are of the same "endianess". It's possible to mask | 
|  | * this with blank #define HASH_BLOCK_DATA_ORDER though... | 
|  | * | 
|  | *				<appro@fy.chalmers.se> | 
|  | */ | 
|  | #if defined(B_ENDIAN) | 
|  | #  if defined(DATA_ORDER_IS_BIG_ENDIAN) | 
|  | #    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 | 
|  | #      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER | 
|  | #    endif | 
|  | #  elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) | 
|  | #    ifndef HOST_FETCH32 | 
|  | #      ifdef LE_FETCH32 | 
|  | #        define HOST_FETCH32(p,l)	LE_FETCH32(p) | 
|  | #      elif defined(REVERSE_FETCH32) | 
|  | #        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l) | 
|  | #      endif | 
|  | #    endif | 
|  | #  endif | 
|  | #elif defined(L_ENDIAN) | 
|  | #  if defined(DATA_ORDER_IS_LITTLE_ENDIAN) | 
|  | #    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2 | 
|  | #      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER | 
|  | #    endif | 
|  | #  elif defined(DATA_ORDER_IS_BIG_ENDIAN) | 
|  | #    ifndef HOST_FETCH32 | 
|  | #      ifdef BE_FETCH32 | 
|  | #        define HOST_FETCH32(p,l)	BE_FETCH32(p) | 
|  | #      elif defined(REVERSE_FETCH32) | 
|  | #        define HOST_FETCH32(p,l)	REVERSE_FETCH32(p,l) | 
|  | #      endif | 
|  | #    endif | 
|  | #  endif | 
|  | #endif | 
|  |  | 
|  | #if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) | 
|  | #ifndef HASH_BLOCK_DATA_ORDER | 
|  | #error "HASH_BLOCK_DATA_ORDER must be defined!" | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | #if defined(DATA_ORDER_IS_BIG_ENDIAN) | 
|  |  | 
|  | #define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))<<24),		\ | 
|  | l|=(((unsigned long)(*((c)++)))<<16),		\ | 
|  | l|=(((unsigned long)(*((c)++)))<< 8),		\ | 
|  | l|=(((unsigned long)(*((c)++)))    ),		\ | 
|  | l) | 
|  | #define HOST_p_c2l(c,l,n)	{					\ | 
|  | switch (n) {					\ | 
|  | case 0: l =((unsigned long)(*((c)++)))<<24;	\ | 
|  | case 1: l|=((unsigned long)(*((c)++)))<<16;	\ | 
|  | case 2: l|=((unsigned long)(*((c)++)))<< 8;	\ | 
|  | case 3: l|=((unsigned long)(*((c)++)));		\ | 
|  | } } | 
|  | #define HOST_p_c2l_p(c,l,sc,len) {					\ | 
|  | switch (sc) {					\ | 
|  | case 0: l =((unsigned long)(*((c)++)))<<24;	\ | 
|  | if (--len == 0) break;			\ | 
|  | case 1: l|=((unsigned long)(*((c)++)))<<16;	\ | 
|  | if (--len == 0) break;			\ | 
|  | case 2: l|=((unsigned long)(*((c)++)))<< 8;	\ | 
|  | } } | 
|  | /* NOTE the pointer is not incremented at the end of this */ | 
|  | #define HOST_c2l_p(c,l,n)	{					\ | 
|  | l=0; (c)+=n;					\ | 
|  | switch (n) {					\ | 
|  | case 3: l =((unsigned long)(*(--(c))))<< 8;	\ | 
|  | case 2: l|=((unsigned long)(*(--(c))))<<16;	\ | 
|  | case 1: l|=((unsigned long)(*(--(c))))<<24;	\ | 
|  | } } | 
|  | #define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff),	\ | 
|  | *((c)++)=(unsigned char)(((l)>>16)&0xff),	\ | 
|  | *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\ | 
|  | *((c)++)=(unsigned char)(((l)    )&0xff),	\ | 
|  | l) | 
|  |  | 
|  | #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) | 
|  |  | 
|  | #define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))    ),		\ | 
|  | l|=(((unsigned long)(*((c)++)))<< 8),		\ | 
|  | l|=(((unsigned long)(*((c)++)))<<16),		\ | 
|  | l|=(((unsigned long)(*((c)++)))<<24),		\ | 
|  | l) | 
|  | #define HOST_p_c2l(c,l,n)	{					\ | 
|  | switch (n) {					\ | 
|  | case 0: l =((unsigned long)(*((c)++)));		\ | 
|  | case 1: l|=((unsigned long)(*((c)++)))<< 8;	\ | 
|  | case 2: l|=((unsigned long)(*((c)++)))<<16;	\ | 
|  | case 3: l|=((unsigned long)(*((c)++)))<<24;	\ | 
|  | } } | 
|  | #define HOST_p_c2l_p(c,l,sc,len) {					\ | 
|  | switch (sc) {					\ | 
|  | case 0: l =((unsigned long)(*((c)++)));		\ | 
|  | if (--len == 0) break;			\ | 
|  | case 1: l|=((unsigned long)(*((c)++)))<< 8;	\ | 
|  | if (--len == 0) break;			\ | 
|  | case 2: l|=((unsigned long)(*((c)++)))<<16;	\ | 
|  | } } | 
|  | /* NOTE the pointer is not incremented at the end of this */ | 
|  | #define HOST_c2l_p(c,l,n)	{					\ | 
|  | l=0; (c)+=n;					\ | 
|  | switch (n) {					\ | 
|  | case 3: l =((unsigned long)(*(--(c))))<<16;	\ | 
|  | case 2: l|=((unsigned long)(*(--(c))))<< 8;	\ | 
|  | case 1: l|=((unsigned long)(*(--(c))));		\ | 
|  | } } | 
|  | #define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff),	\ | 
|  | *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\ | 
|  | *((c)++)=(unsigned char)(((l)>>16)&0xff),	\ | 
|  | *((c)++)=(unsigned char)(((l)>>24)&0xff),	\ | 
|  | l) | 
|  |  | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * Time for some action:-) | 
|  | */ | 
|  |  | 
|  | void HASH_UPDATE (HASH_CTX *c, const unsigned char *data, unsigned long len) | 
|  | { | 
|  | register HASH_LONG * p; | 
|  | register unsigned long l; | 
|  | int sw,sc,ew,ec; | 
|  |  | 
|  | if (len==0) return; | 
|  |  | 
|  | l=(c->Nl+(len<<3))&0xffffffffL; | 
|  | /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to | 
|  | * Wei Dai <weidai@eskimo.com> for pointing it out. */ | 
|  | if (l < c->Nl) /* overflow */ | 
|  | c->Nh++; | 
|  | c->Nh+=(len>>29); | 
|  | c->Nl=l; | 
|  |  | 
|  | if (c->num != 0) | 
|  | { | 
|  | p=c->data; | 
|  | sw=c->num>>2; | 
|  | sc=c->num&0x03; | 
|  |  | 
|  | if ((c->num+len) >= HASH_CBLOCK) | 
|  | { | 
|  | l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; | 
|  | for (; sw<HASH_LBLOCK; sw++) | 
|  | { | 
|  | HOST_c2l(data,l); p[sw]=l; | 
|  | } | 
|  | HASH_BLOCK_HOST_ORDER (c,p,1); | 
|  | len-=(HASH_CBLOCK-c->num); | 
|  | c->num=0; | 
|  | /* drop through and do the rest */ | 
|  | } | 
|  | else | 
|  | { | 
|  | c->num+=len; | 
|  | if ((sc+len) < 4) /* ugly, add char's to a word */ | 
|  | { | 
|  | l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l; | 
|  | } | 
|  | else | 
|  | { | 
|  | ew=(c->num>>2); | 
|  | ec=(c->num&0x03); | 
|  | l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l; | 
|  | for (; sw < ew; sw++) | 
|  | { | 
|  | HOST_c2l(data,l); p[sw]=l; | 
|  | } | 
|  | if (ec) | 
|  | { | 
|  | HOST_c2l_p(data,l,ec); p[sw]=l; | 
|  | } | 
|  | } | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | sw=len/HASH_CBLOCK; | 
|  | if (sw > 0) | 
|  | { | 
|  | #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) | 
|  | /* | 
|  | * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined | 
|  | * only if sizeof(HASH_LONG)==4. | 
|  | */ | 
|  | if ((((unsigned long)data)%4) == 0) | 
|  | { | 
|  | /* data is properly aligned so that we can cast it: */ | 
|  | HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw); | 
|  | sw*=HASH_CBLOCK; | 
|  | data+=sw; | 
|  | len-=sw; | 
|  | } | 
|  | else | 
|  | #if !defined(HASH_BLOCK_DATA_ORDER) | 
|  | while (sw--) | 
|  | { | 
|  | memcpy (p=c->data,data,HASH_CBLOCK); | 
|  | HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1); | 
|  | data+=HASH_CBLOCK; | 
|  | len-=HASH_CBLOCK; | 
|  | } | 
|  | #endif | 
|  | #endif | 
|  | #if defined(HASH_BLOCK_DATA_ORDER) | 
|  | { | 
|  | HASH_BLOCK_DATA_ORDER(c,data,sw); | 
|  | sw*=HASH_CBLOCK; | 
|  | data+=sw; | 
|  | len-=sw; | 
|  | } | 
|  | #endif | 
|  | } | 
|  |  | 
|  | if (len!=0) | 
|  | { | 
|  | p = c->data; | 
|  | c->num = len; | 
|  | ew=len>>2;	/* words to copy */ | 
|  | ec=len&0x03; | 
|  | for (; ew; ew--,p++) | 
|  | { | 
|  | HOST_c2l(data,l); *p=l; | 
|  | } | 
|  | HOST_c2l_p(data,l,ec); | 
|  | *p=l; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) | 
|  | { | 
|  | #if defined(HASH_BLOCK_DATA_ORDER_ALIGNED) | 
|  | if ((((unsigned long)data)%4) == 0) | 
|  | /* data is properly aligned so that we can cast it: */ | 
|  | HASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1); | 
|  | else | 
|  | #if !defined(HASH_BLOCK_DATA_ORDER) | 
|  | { | 
|  | memcpy (c->data,data,HASH_CBLOCK); | 
|  | HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1); | 
|  | } | 
|  | #endif | 
|  | #endif | 
|  | #if defined(HASH_BLOCK_DATA_ORDER) | 
|  | HASH_BLOCK_DATA_ORDER (c,data,1); | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | void HASH_FINAL (unsigned char *md, HASH_CTX *c) | 
|  | { | 
|  | register HASH_LONG *p; | 
|  | register unsigned long l; | 
|  | register int i,j; | 
|  | static const unsigned char end[4]={0x80,0x00,0x00,0x00}; | 
|  | const unsigned char *cp=end; | 
|  |  | 
|  | /* c->num should definitly have room for at least one more byte. */ | 
|  | p=c->data; | 
|  | i=c->num>>2; | 
|  | j=c->num&0x03; | 
|  |  | 
|  | #if 0 | 
|  | /* purify often complains about the following line as an | 
|  | * Uninitialized Memory Read.  While this can be true, the | 
|  | * following p_c2l macro will reset l when that case is true. | 
|  | * This is because j&0x03 contains the number of 'valid' bytes | 
|  | * already in p[i].  If and only if j&0x03 == 0, the UMR will | 
|  | * occur but this is also the only time p_c2l will do | 
|  | * l= *(cp++) instead of l|= *(cp++) | 
|  | * Many thanks to Alex Tang <altitude@cic.net> for pickup this | 
|  | * 'potential bug' */ | 
|  | #ifdef PURIFY | 
|  | if (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */ | 
|  | #endif | 
|  | l=p[i]; | 
|  | #else | 
|  | l = (j==0) ? 0 : p[i]; | 
|  | #endif | 
|  | HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */ | 
|  |  | 
|  | if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */ | 
|  | { | 
|  | if (i<HASH_LBLOCK) p[i]=0; | 
|  | HASH_BLOCK_HOST_ORDER (c,p,1); | 
|  | i=0; | 
|  | } | 
|  | for (; i<(HASH_LBLOCK-2); i++) | 
|  | p[i]=0; | 
|  |  | 
|  | #if   defined(DATA_ORDER_IS_BIG_ENDIAN) | 
|  | p[HASH_LBLOCK-2]=c->Nh; | 
|  | p[HASH_LBLOCK-1]=c->Nl; | 
|  | #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) | 
|  | p[HASH_LBLOCK-2]=c->Nl; | 
|  | p[HASH_LBLOCK-1]=c->Nh; | 
|  | #endif | 
|  | HASH_BLOCK_HOST_ORDER (c,p,1); | 
|  |  | 
|  | #ifndef HASH_MAKE_STRING | 
|  | #error "HASH_MAKE_STRING must be defined!" | 
|  | #else | 
|  | HASH_MAKE_STRING(c,md); | 
|  | #endif | 
|  |  | 
|  | c->num=0; | 
|  | /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack | 
|  | * but I'm not worried :-) | 
|  | memset((void *)c,0,sizeof(HASH_CTX)); | 
|  | */ | 
|  | } |