155714Skris/* crypto/md32_common.h */
255714Skris/* ====================================================================
3194206Ssimon * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
455714Skris *
555714Skris * Redistribution and use in source and binary forms, with or without
655714Skris * modification, are permitted provided that the following conditions
755714Skris * are met:
855714Skris *
955714Skris * 1. Redistributions of source code must retain the above copyright
1055714Skris *    notice, this list of conditions and the following disclaimer.
1155714Skris *
1255714Skris * 2. Redistributions in binary form must reproduce the above copyright
1355714Skris *    notice, this list of conditions and the following disclaimer in
1455714Skris *    the documentation and/or other materials provided with the
1555714Skris *    distribution.
1655714Skris *
1755714Skris * 3. All advertising materials mentioning features or use of this
1855714Skris *    software must display the following acknowledgment:
1955714Skris *    "This product includes software developed by the OpenSSL Project
2055714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2155714Skris *
2255714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2355714Skris *    endorse or promote products derived from this software without
2455714Skris *    prior written permission. For written permission, please contact
2555714Skris *    licensing@OpenSSL.org.
2655714Skris *
2755714Skris * 5. Products derived from this software may not be called "OpenSSL"
2855714Skris *    nor may "OpenSSL" appear in their names without prior written
2955714Skris *    permission of the OpenSSL Project.
3055714Skris *
3155714Skris * 6. Redistributions of any form whatsoever must retain the following
3255714Skris *    acknowledgment:
3355714Skris *    "This product includes software developed by the OpenSSL Project
3455714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3555714Skris *
3655714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
3755714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3855714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3955714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4055714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4155714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4255714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4355714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4455714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4555714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4655714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4755714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
4855714Skris * ====================================================================
4955714Skris *
5055714Skris */
5155714Skris
5255714Skris/*
5355714Skris * This is a generic 32 bit "collector" for message digest algorithms.
5455714Skris * Whenever needed it collects input character stream into chunks of
5555714Skris * 32 bit values and invokes a block function that performs actual hash
5655714Skris * calculations.
5755714Skris *
5855714Skris * Porting guide.
5955714Skris *
6055714Skris * Obligatory macros:
6155714Skris *
6255714Skris * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
6355714Skris *	this macro defines byte order of input stream.
6455714Skris * HASH_CBLOCK
6555714Skris *	size of a unit chunk HASH_BLOCK operates on.
6655714Skris * HASH_LONG
6755714Skris *	has to be at lest 32 bit wide, if it's wider, then
6855714Skris *	HASH_LONG_LOG2 *has to* be defined along
6955714Skris * HASH_CTX
7055714Skris *	context structure that at least contains following
7155714Skris *	members:
7255714Skris *		typedef struct {
7355714Skris *			...
7455714Skris *			HASH_LONG	Nl,Nh;
75194206Ssimon *			either {
7655714Skris *			HASH_LONG	data[HASH_LBLOCK];
77194206Ssimon *			unsigned char	data[HASH_CBLOCK];
78194206Ssimon *			};
79160814Ssimon *			unsigned int	num;
8055714Skris *			...
8155714Skris *			} HASH_CTX;
82194206Ssimon *	data[] vector is expected to be zeroed upon first call to
83194206Ssimon *	HASH_UPDATE.
8455714Skris * HASH_UPDATE
8555714Skris *	name of "Update" function, implemented here.
8655714Skris * HASH_TRANSFORM
8755714Skris *	name of "Transform" function, implemented here.
8855714Skris * HASH_FINAL
8955714Skris *	name of "Final" function, implemented here.
9055714Skris * HASH_BLOCK_DATA_ORDER
91194206Ssimon *	name of "block" function capable of treating *unaligned* input
92194206Ssimon *	message in original (data) byte order, implemented externally.
9359191Skris * HASH_MAKE_STRING
9459191Skris *	macro convering context variables to an ASCII hash string.
9555714Skris *
9655714Skris * MD5 example:
9755714Skris *
9855714Skris *	#define DATA_ORDER_IS_LITTLE_ENDIAN
9955714Skris *
10055714Skris *	#define HASH_LONG		MD5_LONG
10155714Skris *	#define HASH_LONG_LOG2		MD5_LONG_LOG2
10255714Skris *	#define HASH_CTX		MD5_CTX
10355714Skris *	#define HASH_CBLOCK		MD5_CBLOCK
10455714Skris *	#define HASH_UPDATE		MD5_Update
10555714Skris *	#define HASH_TRANSFORM		MD5_Transform
10655714Skris *	#define HASH_FINAL		MD5_Final
10755714Skris *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
10855714Skris *
10955714Skris *					<appro@fy.chalmers.se>
11055714Skris */
11155714Skris
11255714Skris#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
11355714Skris#error "DATA_ORDER must be defined!"
11455714Skris#endif
11555714Skris
11655714Skris#ifndef HASH_CBLOCK
11755714Skris#error "HASH_CBLOCK must be defined!"
11855714Skris#endif
11955714Skris#ifndef HASH_LONG
12055714Skris#error "HASH_LONG must be defined!"
12155714Skris#endif
12255714Skris#ifndef HASH_CTX
12355714Skris#error "HASH_CTX must be defined!"
12455714Skris#endif
12555714Skris
12655714Skris#ifndef HASH_UPDATE
12755714Skris#error "HASH_UPDATE must be defined!"
12855714Skris#endif
12955714Skris#ifndef HASH_TRANSFORM
13055714Skris#error "HASH_TRANSFORM must be defined!"
13155714Skris#endif
13255714Skris#ifndef HASH_FINAL
13355714Skris#error "HASH_FINAL must be defined!"
13455714Skris#endif
13555714Skris
13655714Skris#ifndef HASH_BLOCK_DATA_ORDER
13755714Skris#error "HASH_BLOCK_DATA_ORDER must be defined!"
13855714Skris#endif
13955714Skris
14055714Skris/*
14155714Skris * Engage compiler specific rotate intrinsic function if available.
14255714Skris */
14355714Skris#undef ROTATE
14455714Skris#ifndef PEDANTIC
145160814Ssimon# if defined(_MSC_VER) || defined(__ICC)
14659191Skris#  define ROTATE(a,n)	_lrotl(a,n)
14759191Skris# elif defined(__MWERKS__)
14859191Skris#  if defined(__POWERPC__)
14959191Skris#   define ROTATE(a,n)	__rlwinm(a,n,0,31)
15059191Skris#  elif defined(__MC68K__)
15159191Skris    /* Motorola specific tweak. <appro@fy.chalmers.se> */
15259191Skris#   define ROTATE(a,n)	( n<24 ? __rol(a,n) : __ror(a,32-n) )
15359191Skris#  else
15459191Skris#   define ROTATE(a,n)	__rol(a,n)
15559191Skris#  endif
156109998Smarkm# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
15755714Skris  /*
15855714Skris   * Some GNU C inline assembler templates. Note that these are
15955714Skris   * rotates by *constant* number of bits! But that's exactly
16055714Skris   * what we need here...
16155714Skris   * 					<appro@fy.chalmers.se>
16255714Skris   */
163109998Smarkm#  if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
16455714Skris#   define ROTATE(a,n)	({ register unsigned int ret;	\
16559191Skris				asm (			\
16655714Skris				"roll %1,%0"		\
16755714Skris				: "=r"(ret)		\
168212961Srpaulo				: "I"(n), "0"((unsigned int)(a))	\
16955714Skris				: "cc");		\
17055714Skris			   ret;				\
17155714Skris			})
172194206Ssimon#  elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
173194206Ssimon	defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__)
17455714Skris#   define ROTATE(a,n)	({ register unsigned int ret;	\
17559191Skris				asm (			\
17655714Skris				"rlwinm %0,%1,%2,0,31"	\
17755714Skris				: "=r"(ret)		\
17855714Skris				: "r"(a), "I"(n));	\
17955714Skris			   ret;				\
18055714Skris			})
181194206Ssimon#  elif defined(__s390x__)
182194206Ssimon#   define ROTATE(a,n) ({ register unsigned int ret;	\
183194206Ssimon				asm ("rll %0,%1,%2"	\
184194206Ssimon				: "=r"(ret)		\
185194206Ssimon				: "r"(a), "I"(n));	\
186194206Ssimon			  ret;				\
187194206Ssimon			})
18855714Skris#  endif
18955714Skris# endif
19055714Skris#endif /* PEDANTIC */
19155714Skris
19255714Skris#ifndef ROTATE
19355714Skris#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
19455714Skris#endif
19555714Skris
19655714Skris#if defined(DATA_ORDER_IS_BIG_ENDIAN)
19755714Skris
198160814Ssimon#ifndef PEDANTIC
199160814Ssimon# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
200160814Ssimon#  if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \
201160814Ssimon      (defined(__x86_64) || defined(__x86_64__))
202194206Ssimon#   if !defined(B_ENDIAN)
203160814Ssimon    /*
204160814Ssimon     * This gives ~30-40% performance improvement in SHA-256 compiled
205160814Ssimon     * with gcc [on P4]. Well, first macro to be frank. We can pull
206160814Ssimon     * this trick on x86* platforms only, because these CPUs can fetch
207160814Ssimon     * unaligned data without raising an exception.
208160814Ssimon     */
209160814Ssimon#   define HOST_c2l(c,l)	({ unsigned int r=*((const unsigned int *)(c));	\
210160814Ssimon				   asm ("bswapl %0":"=r"(r):"0"(r));	\
211160814Ssimon				   (c)+=4; (l)=r;			})
212160814Ssimon#   define HOST_l2c(l,c)	({ unsigned int r=(l);			\
213160814Ssimon				   asm ("bswapl %0":"=r"(r):"0"(r));	\
214160814Ssimon				   *((unsigned int *)(c))=r; (c)+=4; r;	})
215194206Ssimon#   endif
216160814Ssimon#  endif
217160814Ssimon# endif
218160814Ssimon#endif
219194206Ssimon#if defined(__s390__) || defined(__s390x__)
220194206Ssimon# define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l))
221194206Ssimon# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l))
222194206Ssimon#endif
223160814Ssimon
224160814Ssimon#ifndef HOST_c2l
22555714Skris#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))<<24),		\
22655714Skris			 l|=(((unsigned long)(*((c)++)))<<16),		\
22755714Skris			 l|=(((unsigned long)(*((c)++)))<< 8),		\
228279264Sdelphij			 l|=(((unsigned long)(*((c)++)))    )		)
229160814Ssimon#endif
230160814Ssimon#ifndef HOST_l2c
23155714Skris#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff),	\
23255714Skris			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
23355714Skris			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
23455714Skris			 *((c)++)=(unsigned char)(((l)    )&0xff),	\
23555714Skris			 l)
236160814Ssimon#endif
23755714Skris
23855714Skris#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
23955714Skris
240194206Ssimon#ifndef PEDANTIC
241194206Ssimon# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
242194206Ssimon#  if defined(__s390x__)
243206046Ssimon#   define HOST_c2l(c,l)	({ asm ("lrv	%0,%1"			\
244215697Ssimon				   :"=d"(l) :"m"(*(const unsigned int *)(c)));\
245194206Ssimon				   (c)+=4; (l);				})
246206046Ssimon#   define HOST_l2c(l,c)	({ asm ("strv	%1,%0"			\
247206046Ssimon				   :"=m"(*(unsigned int *)(c)) :"d"(l));\
248194206Ssimon				   (c)+=4; (l);				})
249194206Ssimon#  endif
250194206Ssimon# endif
251194206Ssimon#endif
252160814Ssimon#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
253160814Ssimon# ifndef B_ENDIAN
254160814Ssimon   /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
255160814Ssimon#  define HOST_c2l(c,l)	((l)=*((const unsigned int *)(c)), (c)+=4, l)
256160814Ssimon#  define HOST_l2c(l,c)	(*((unsigned int *)(c))=(l), (c)+=4, l)
257160814Ssimon# endif
258160814Ssimon#endif
259160814Ssimon
260160814Ssimon#ifndef HOST_c2l
26155714Skris#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))    ),		\
26255714Skris			 l|=(((unsigned long)(*((c)++)))<< 8),		\
26355714Skris			 l|=(((unsigned long)(*((c)++)))<<16),		\
264279264Sdelphij			 l|=(((unsigned long)(*((c)++)))<<24)		)
265160814Ssimon#endif
266160814Ssimon#ifndef HOST_l2c
26755714Skris#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff),	\
26855714Skris			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
26955714Skris			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
27055714Skris			 *((c)++)=(unsigned char)(((l)>>24)&0xff),	\
27155714Skris			 l)
272160814Ssimon#endif
27355714Skris
27455714Skris#endif
27555714Skris
27655714Skris/*
27755714Skris * Time for some action:-)
27855714Skris */
27955714Skris
280160814Ssimonint HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
28155714Skris	{
28259191Skris	const unsigned char *data=data_;
283194206Ssimon	unsigned char *p;
284194206Ssimon	HASH_LONG l;
285194206Ssimon	size_t n;
28655714Skris
287109998Smarkm	if (len==0) return 1;
28855714Skris
289160814Ssimon	l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL;
29055714Skris	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
29155714Skris	 * Wei Dai <weidai@eskimo.com> for pointing it out. */
29255714Skris	if (l < c->Nl) /* overflow */
29355714Skris		c->Nh++;
294238405Sjkim	c->Nh+=(HASH_LONG)(len>>29);	/* might cause compiler warning on 16-bit */
29555714Skris	c->Nl=l;
29655714Skris
297194206Ssimon	n = c->num;
298194206Ssimon	if (n != 0)
29955714Skris		{
300194206Ssimon		p=(unsigned char *)c->data;
30155714Skris
302194206Ssimon		if (len >= HASH_CBLOCK || len+n >= HASH_CBLOCK)
30355714Skris			{
304194206Ssimon			memcpy (p+n,data,HASH_CBLOCK-n);
305194206Ssimon			HASH_BLOCK_DATA_ORDER (c,p,1);
306194206Ssimon			n      = HASH_CBLOCK-n;
307194206Ssimon			data  += n;
308194206Ssimon			len   -= n;
309194206Ssimon			c->num = 0;
310194206Ssimon			memset (p,0,HASH_CBLOCK);	/* keep it zeroed */
31155714Skris			}
31255714Skris		else
31355714Skris			{
314194206Ssimon			memcpy (p+n,data,len);
315194206Ssimon			c->num += (unsigned int)len;
316109998Smarkm			return 1;
31755714Skris			}
31855714Skris		}
31955714Skris
320194206Ssimon	n = len/HASH_CBLOCK;
321194206Ssimon	if (n > 0)
32255714Skris		{
323194206Ssimon		HASH_BLOCK_DATA_ORDER (c,data,n);
324194206Ssimon		n    *= HASH_CBLOCK;
325194206Ssimon		data += n;
326194206Ssimon		len  -= n;
32755714Skris		}
32855714Skris
329194206Ssimon	if (len != 0)
33055714Skris		{
331194206Ssimon		p = (unsigned char *)c->data;
332238405Sjkim		c->num = (unsigned int)len;
333194206Ssimon		memcpy (p,data,len);
33455714Skris		}
335109998Smarkm	return 1;
33655714Skris	}
33755714Skris
33855714Skris
33955714Skrisvoid HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
34055714Skris	{
34155714Skris	HASH_BLOCK_DATA_ORDER (c,data,1);
34255714Skris	}
34355714Skris
34455714Skris
345109998Smarkmint HASH_FINAL (unsigned char *md, HASH_CTX *c)
34655714Skris	{
347194206Ssimon	unsigned char *p = (unsigned char *)c->data;
348194206Ssimon	size_t n = c->num;
34955714Skris
350194206Ssimon	p[n] = 0x80; /* there is always room for one */
351194206Ssimon	n++;
35255714Skris
353194206Ssimon	if (n > (HASH_CBLOCK-8))
35455714Skris		{
355194206Ssimon		memset (p+n,0,HASH_CBLOCK-n);
356194206Ssimon		n=0;
357194206Ssimon		HASH_BLOCK_DATA_ORDER (c,p,1);
35855714Skris		}
359194206Ssimon	memset (p+n,0,HASH_CBLOCK-8-n);
36055714Skris
361194206Ssimon	p += HASH_CBLOCK-8;
36255714Skris#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
363194206Ssimon	(void)HOST_l2c(c->Nh,p);
364194206Ssimon	(void)HOST_l2c(c->Nl,p);
36555714Skris#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
366194206Ssimon	(void)HOST_l2c(c->Nl,p);
367194206Ssimon	(void)HOST_l2c(c->Nh,p);
36855714Skris#endif
369194206Ssimon	p -= HASH_CBLOCK;
370194206Ssimon	HASH_BLOCK_DATA_ORDER (c,p,1);
371194206Ssimon	c->num=0;
372194206Ssimon	memset (p,0,HASH_CBLOCK);
37355714Skris
37459191Skris#ifndef HASH_MAKE_STRING
37559191Skris#error "HASH_MAKE_STRING must be defined!"
37659191Skris#else
37759191Skris	HASH_MAKE_STRING(c,md);
37859191Skris#endif
37955714Skris
380109998Smarkm	return 1;
38155714Skris	}
382109998Smarkm
383109998Smarkm#ifndef MD32_REG_T
384212961Srpaulo#if defined(__alpha) || defined(__sparcv9) || defined(__mips)
385109998Smarkm#define MD32_REG_T long
386109998Smarkm/*
387109998Smarkm * This comment was originaly written for MD5, which is why it
388109998Smarkm * discusses A-D. But it basically applies to all 32-bit digests,
389109998Smarkm * which is why it was moved to common header file.
390109998Smarkm *
391109998Smarkm * In case you wonder why A-D are declared as long and not
392109998Smarkm * as MD5_LONG. Doing so results in slight performance
393109998Smarkm * boost on LP64 architectures. The catch is we don't
394109998Smarkm * really care if 32 MSBs of a 64-bit register get polluted
395109998Smarkm * with eventual overflows as we *save* only 32 LSBs in
396109998Smarkm * *either* case. Now declaring 'em long excuses the compiler
397109998Smarkm * from keeping 32 MSBs zeroed resulting in 13% performance
398109998Smarkm * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
399109998Smarkm * Well, to be honest it should say that this *prevents*
400109998Smarkm * performance degradation.
401109998Smarkm *				<appro@fy.chalmers.se>
402212961Srpaulo */
403212961Srpaulo#else
404212961Srpaulo/*
405212961Srpaulo * Above is not absolute and there are LP64 compilers that
406212961Srpaulo * generate better code if MD32_REG_T is defined int. The above
407212961Srpaulo * pre-processor condition reflects the circumstances under which
408212961Srpaulo * the conclusion was made and is subject to further extension.
409109998Smarkm *				<appro@fy.chalmers.se>
410109998Smarkm */
411212961Srpaulo#define MD32_REG_T int
412109998Smarkm#endif
413212961Srpaulo#endif
414