md32_common.h 11.8 KB
Newer Older
U
Ulf Möller 已提交
1 2
/* crypto/md32_common.h */
/* ====================================================================
3
 * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
U
Ulf Möller 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
 *
 * 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 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
67
 *	has to be at lest 32 bit wide.
U
Ulf Möller 已提交
68 69 70 71 72 73
 * HASH_CTX
 *	context structure that at least contains following
 *	members:
 *		typedef struct {
 *			...
 *			HASH_LONG	Nl,Nh;
74
 *			either {
75 76
 *			  HASH_LONG	data[HASH_LBLOCK];
 *			  unsigned char	data[HASH_CBLOCK];
77
 *			};
78
 *			unsigned int	num;
U
Ulf Möller 已提交
79 80
 *			...
 *			} HASH_CTX;
81 82
 *	data[] vector is expected to be zeroed upon first call to
 *	HASH_UPDATE.
U
Ulf Möller 已提交
83 84 85 86 87 88 89
 * 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_DATA_ORDER
90 91
 *	name of "block" function capable of treating *unaligned* input
 *	message in original (data) byte order, implemented externally.
92 93
 * HASH_MAKE_STRING
 *	macro convering context variables to an ASCII hash string.
U
Ulf Möller 已提交
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
 *
 * MD5 example:
 *
 *	#define DATA_ORDER_IS_LITTLE_ENDIAN
 *
 *	#define HASH_LONG		MD5_LONG
 *	#define HASH_CTX		MD5_CTX
 *	#define HASH_CBLOCK		MD5_CBLOCK
 *	#define HASH_UPDATE		MD5_Update
 *	#define HASH_TRANSFORM		MD5_Transform
 *	#define HASH_FINAL		MD5_Final
 *	#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_DATA_ORDER
#error "HASH_BLOCK_DATA_ORDER must be defined!"
#endif

/*
 * Engage compiler specific rotate intrinsic function if available.
 */
#undef ROTATE
#ifndef PEDANTIC
143
# if defined(_MSC_VER) || defined(__ICC)
144 145
#  define ROTATE(a,n)	_lrotl(a,n)
# elif defined(__MWERKS__)
A
Andy Polyakov 已提交
146
#  if defined(__POWERPC__)
147
#   define ROTATE(a,n)	__rlwinm(a,n,0,31)
A
Andy Polyakov 已提交
148 149 150
#  elif defined(__MC68K__)
    /* Motorola specific tweak. <appro@fy.chalmers.se> */
#   define ROTATE(a,n)	( n<24 ? __rol(a,n) : __ror(a,32-n) )
A
Andy Polyakov 已提交
151 152 153
#  else
#   define ROTATE(a,n)	__rol(a,n)
#  endif
154
# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
U
Ulf Möller 已提交
155 156 157 158 159 160
  /*
   * 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>
   */
A
Andy Polyakov 已提交
161
#  if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
U
Ulf Möller 已提交
162
#   define ROTATE(a,n)	({ register unsigned int ret;	\
163
				asm (			\
U
Ulf Möller 已提交
164 165 166 167 168 169
				"roll %1,%0"		\
				: "=r"(ret)		\
				: "I"(n), "0"(a)	\
				: "cc");		\
			   ret;				\
			})
A
Andy Polyakov 已提交
170 171
#  elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
	defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__)
U
Ulf Möller 已提交
172
#   define ROTATE(a,n)	({ register unsigned int ret;	\
173
				asm (			\
U
Ulf Möller 已提交
174 175 176 177 178
				"rlwinm %0,%1,%2,0,31"	\
				: "=r"(ret)		\
				: "r"(a), "I"(n));	\
			   ret;				\
			})
179
#  elif defined(__s390x__)
A
Andy Polyakov 已提交
180 181 182
#   define ROTATE(a,n) ({ register unsigned int ret;	\
				asm ("rll %0,%1,%2"	\
				: "=r"(ret)		\
183
				: "r"(a), "I"(n));	\
A
Andy Polyakov 已提交
184 185
			  ret;				\
			})
U
Ulf Möller 已提交
186 187 188 189 190 191 192 193 194 195
#  endif
# endif
#endif /* PEDANTIC */

#ifndef ROTATE
#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
#endif

#if defined(DATA_ORDER_IS_BIG_ENDIAN)

196 197
#ifndef PEDANTIC
# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
A
Andy Polyakov 已提交
198
#  if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \
199
      (defined(__x86_64) || defined(__x86_64__))
200
#   if !defined(B_ENDIAN)
201 202 203 204 205 206
    /*
     * This gives ~30-40% performance improvement in SHA-256 compiled
     * with gcc [on P4]. Well, first macro to be frank. We can pull
     * this trick on x86* platforms only, because these CPUs can fetch
     * unaligned data without raising an exception.
     */
207 208 209
#   define HOST_c2l(c,l)	({ unsigned int r=*((const unsigned int *)(c));	\
				   asm ("bswapl %0":"=r"(r):"0"(r));	\
				   (c)+=4; (l)=r;			})
210 211 212
#   define HOST_l2c(l,c)	({ unsigned int r=(l);			\
				   asm ("bswapl %0":"=r"(r):"0"(r));	\
				   *((unsigned int *)(c))=r; (c)+=4; r;	})
213
#   endif
214 215 216
#  endif
# endif
#endif
A
Andy Polyakov 已提交
217 218 219 220
#if defined(__s390__) || defined(__s390x__)
# define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l))
# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l))
#endif
221 222

#ifndef HOST_c2l
U
Ulf Möller 已提交
223 224 225 226 227
#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)
228 229
#endif
#ifndef HOST_l2c
U
Ulf Möller 已提交
230 231 232 233 234
#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)
235
#endif
U
Ulf Möller 已提交
236 237 238

#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)

A
Andy Polyakov 已提交
239 240 241 242 243 244 245 246 247 248 249 250
#ifndef PEDANTIC
# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
#  if defined(__s390x__)
#   define HOST_c2l(c,l)	({ asm ("lrv	%0,0(%1)"		\
					:"=r"(l) : "r"(c));		\
				   (c)+=4; (l);				})
#   define HOST_l2c(l,c)	({ asm ("strv	%0,0(%1)"		\
					: : "r"(l),"r"(c) : "memory");	\
				   (c)+=4; (l);				})
#  endif
# endif
#endif
251
#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
R
Richard Levitte 已提交
252 253 254 255 256
# ifndef B_ENDIAN
   /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
#  define HOST_c2l(c,l)	((l)=*((const unsigned int *)(c)), (c)+=4, l)
#  define HOST_l2c(l,c)	(*((unsigned int *)(c))=(l), (c)+=4, l)
# endif
257 258 259
#endif

#ifndef HOST_c2l
U
Ulf Möller 已提交
260 261 262 263 264
#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)
265 266
#endif
#ifndef HOST_l2c
U
Ulf Möller 已提交
267 268 269 270 271
#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)
272
#endif
U
Ulf Möller 已提交
273 274 275 276 277 278 279

#endif

/*
 * Time for some action:-)
 */

280
int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
U
Ulf Möller 已提交
281
	{
B
Ben Laurie 已提交
282
	const unsigned char *data=data_;
283 284 285
	unsigned char *p;
	HASH_LONG l;
	size_t n;
U
Ulf Möller 已提交
286

D
 
Dr. Stephen Henson 已提交
287
	if (len==0) return 1;
U
Ulf Möller 已提交
288

289
	l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL;
U
Ulf Möller 已提交
290 291 292 293
	/* 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++;
294
	c->Nh+=(len>>29);	/* might cause compiler warning on 16-bit */
U
Ulf Möller 已提交
295 296
	c->Nl=l;

297 298
	n = c->num;
	if (n != 0)
U
Ulf Möller 已提交
299
		{
300
		p=(unsigned char *)c->data;
U
Ulf Möller 已提交
301

302
		if ((n+len) >= HASH_CBLOCK)
U
Ulf Möller 已提交
303
			{
304 305 306 307 308 309 310
			memcpy (p+n,data,HASH_CBLOCK-n);
			HASH_BLOCK_DATA_ORDER (c,p,1);
			n      = HASH_CBLOCK-n;
			data  += n;
			len   -= n;
			c->num = 0;
			memset (p,0,HASH_CBLOCK);	/* keep it zeroed */
U
Ulf Möller 已提交
311 312 313
			}
		else
			{
314 315
			memcpy (p+n,data,len);
			c->num += (unsigned int)len;
D
 
Dr. Stephen Henson 已提交
316
			return 1;
U
Ulf Möller 已提交
317 318 319
			}
		}

320 321
	n = len/HASH_CBLOCK;
	if (n > 0)
U
Ulf Möller 已提交
322
		{
323 324 325 326
		HASH_BLOCK_DATA_ORDER (c,data,n);
		n    *= HASH_CBLOCK;
		data += n;
		len  -= n;
U
Ulf Möller 已提交
327 328
		}

329
	if (len != 0)
U
Ulf Möller 已提交
330
		{
331
		p = (unsigned char *)c->data;
U
Ulf Möller 已提交
332
		c->num = len;
333
		memcpy (p,data,len);
U
Ulf Möller 已提交
334
		}
D
 
Dr. Stephen Henson 已提交
335
	return 1;
U
Ulf Möller 已提交
336 337 338
	}


B
Ben Laurie 已提交
339
void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
U
Ulf Möller 已提交
340
	{
B
Bodo Möller 已提交
341
	HASH_BLOCK_DATA_ORDER (c,data,1);
U
Ulf Möller 已提交
342 343 344
	}


D
 
Dr. Stephen Henson 已提交
345
int HASH_FINAL (unsigned char *md, HASH_CTX *c)
U
Ulf Möller 已提交
346
	{
347 348
	unsigned char *p = (unsigned char *)c->data;
	size_t n = c->num;
U
Ulf Möller 已提交
349

350 351 352 353
	p[n] = 0x80; /* there is always room for one */
	n++;

	if (n > (HASH_CBLOCK-8))
U
Ulf Möller 已提交
354
		{
355 356
		HASH_BLOCK_DATA_ORDER (c,p,1);
		memset (p,0,HASH_CBLOCK);
U
Ulf Möller 已提交
357 358
		}

359
	p += HASH_CBLOCK-8;
U
Ulf Möller 已提交
360
#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
361 362
	(void)HOST_l2c(c->Nh,p);
	(void)HOST_l2c(c->Nl,p);
U
Ulf Möller 已提交
363
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
364 365
	(void)HOST_l2c(c->Nl,p);
	(void)HOST_l2c(c->Nh,p);
U
Ulf Möller 已提交
366
#endif
367 368 369 370
	p -= HASH_CBLOCK;
	HASH_BLOCK_DATA_ORDER (c,p,1);
	c->num=0;
	memset (p,0,HASH_CBLOCK);
U
Ulf Möller 已提交
371

372 373 374 375 376
#ifndef HASH_MAKE_STRING
#error "HASH_MAKE_STRING must be defined!"
#else
	HASH_MAKE_STRING(c,md);
#endif
U
Ulf Möller 已提交
377

D
 
Dr. Stephen Henson 已提交
378
	return 1;
U
Ulf Möller 已提交
379
	}
A
Andy Polyakov 已提交
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404

#ifndef MD32_REG_T
#define MD32_REG_T long
/*
 * This comment was originaly written for MD5, which is why it
 * discusses A-D. But it basically applies to all 32-bit digests,
 * which is why it was moved to common header file.
 *
 * In case you wonder why A-D are declared as long and not
 * as MD5_LONG. Doing so results in slight performance
 * boost on LP64 architectures. The catch is we don't
 * really care if 32 MSBs of a 64-bit register get polluted
 * with eventual overflows as we *save* only 32 LSBs in
 * *either* case. Now declaring 'em long excuses the compiler
 * from keeping 32 MSBs zeroed resulting in 13% performance
 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
 * Well, to be honest it should say that this *prevents* 
 * performance degradation.
 *				<appro@fy.chalmers.se>
 * Apparently there're LP64 compilers that generate better
 * code if A-D are declared int. Most notably GCC-x86_64
 * generates better code.
 *				<appro@fy.chalmers.se>
 */
#endif