Home | History | Annotate | Download | only in digest
      1 /* ====================================================================
      2  * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in
     13  *    the documentation and/or other materials provided with the
     14  *    distribution.
     15  *
     16  * 3. All advertising materials mentioning features or use of this
     17  *    software must display the following acknowledgment:
     18  *    "This product includes software developed by the OpenSSL Project
     19  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     20  *
     21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     22  *    endorse or promote products derived from this software without
     23  *    prior written permission. For written permission, please contact
     24  *    licensing (at) OpenSSL.org.
     25  *
     26  * 5. Products derived from this software may not be called "OpenSSL"
     27  *    nor may "OpenSSL" appear in their names without prior written
     28  *    permission of the OpenSSL Project.
     29  *
     30  * 6. Redistributions of any form whatsoever must retain the following
     31  *    acknowledgment:
     32  *    "This product includes software developed by the OpenSSL Project
     33  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     34  *
     35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     46  * OF THE POSSIBILITY OF SUCH DAMAGE.
     47  * ==================================================================== */
     48 
     49 #ifndef OPENSSL_HEADER_MD32_COMMON_H
     50 #define OPENSSL_HEADER_MD32_COMMON_H
     51 
     52 #include <openssl/base.h>
     53 
     54 
     55 #if defined(__cplusplus)
     56 extern "C" {
     57 #endif
     58 
     59 #define asm __asm__
     60 
     61 /* This is a generic 32 bit "collector" for message digest algorithms.
     62  * Whenever needed it collects input character stream into chunks of
     63  * 32 bit values and invokes a block function that performs actual hash
     64  * calculations.
     65  *
     66  * Porting guide.
     67  *
     68  * Obligatory macros:
     69  *
     70  * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
     71  *	this macro defines byte order of input stream.
     72  * HASH_CBLOCK
     73  *	size of a unit chunk HASH_BLOCK operates on.
     74  * HASH_LONG
     75  *	has to be at least 32 bit wide.
     76  * HASH_CTX
     77  *	context structure that at least contains following
     78  *	members:
     79  *		typedef struct {
     80  *			...
     81  *			HASH_LONG	Nl,Nh;
     82  *			either {
     83  *			HASH_LONG	data[HASH_LBLOCK];
     84  *			unsigned char	data[HASH_CBLOCK];
     85  *			};
     86  *			unsigned int	num;
     87  *			...
     88  *			} HASH_CTX;
     89  *	data[] vector is expected to be zeroed upon first call to
     90  *	HASH_UPDATE.
     91  * HASH_UPDATE
     92  *	name of "Update" function, implemented here.
     93  * HASH_TRANSFORM
     94  *	name of "Transform" function, implemented here.
     95  * HASH_FINAL
     96  *	name of "Final" function, implemented here.
     97  * HASH_BLOCK_DATA_ORDER
     98  *	name of "block" function capable of treating *unaligned* input
     99  *	message in original (data) byte order, implemented externally.
    100  * HASH_MAKE_STRING
    101  *	macro convering context variables to an ASCII hash string.
    102  *
    103  *					<appro (at) fy.chalmers.se>
    104  */
    105 
    106 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
    107 #error "DATA_ORDER must be defined!"
    108 #endif
    109 
    110 #ifndef HASH_CBLOCK
    111 #error "HASH_CBLOCK must be defined!"
    112 #endif
    113 #ifndef HASH_LONG
    114 #error "HASH_LONG must be defined!"
    115 #endif
    116 #ifndef HASH_CTX
    117 #error "HASH_CTX must be defined!"
    118 #endif
    119 
    120 #ifndef HASH_UPDATE
    121 #error "HASH_UPDATE must be defined!"
    122 #endif
    123 #ifndef HASH_TRANSFORM
    124 #error "HASH_TRANSFORM must be defined!"
    125 #endif
    126 #ifndef HASH_FINAL
    127 #error "HASH_FINAL must be defined!"
    128 #endif
    129 
    130 #ifndef HASH_BLOCK_DATA_ORDER
    131 #error "HASH_BLOCK_DATA_ORDER must be defined!"
    132 #endif
    133 
    134 /*
    135  * Engage compiler specific rotate intrinsic function if available.
    136  */
    137 #undef ROTATE
    138 # if defined(_MSC_VER)
    139 #  define ROTATE(a,n)	_lrotl(a,n)
    140 # elif defined(__ICC)
    141 #  define ROTATE(a,n)	_rotl(a,n)
    142 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM)
    143   /*
    144    * Some GNU C inline assembler templates. Note that these are
    145    * rotates by *constant* number of bits! But that's exactly
    146    * what we need here...
    147    * 					<appro (at) fy.chalmers.se>
    148    */
    149 #  if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
    150 #   define ROTATE(a,n)	({ register uint32_t ret;	\
    151 				asm (			\
    152 				"roll %1,%0"		\
    153 				: "=r"(ret)		\
    154 				: "I"(n), "0"((uint32_t)(a))	\
    155 				: "cc");		\
    156 			   ret;				\
    157 			})
    158 #  endif /* OPENSSL_X86 || OPENSSL_X86_64 */
    159 # endif /* COMPILER */
    160 
    161 #ifndef ROTATE
    162 #define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
    163 #endif
    164 
    165 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
    166 
    167 #ifndef PEDANTIC
    168 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM)
    169 # if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
    170     /*
    171      * This gives ~30-40% performance improvement in SHA-256 compiled
    172      * with gcc [on P4]. Well, first macro to be frank. We can pull
    173      * this trick on x86* platforms only, because these CPUs can fetch
    174      * unaligned data without raising an exception.
    175      */
    176 #   define HOST_c2l(c,l)	({ uint32_t r=*((const uint32_t *)(c));	\
    177 				   asm ("bswapl %0":"=r"(r):"0"(r));	\
    178 				   (c)+=4; (l)=r;			})
    179 #   define HOST_l2c(l,c)	({ uint32_t r=(l);			\
    180 				   asm ("bswapl %0":"=r"(r):"0"(r));	\
    181 				   *((uint32_t *)(c))=r; (c)+=4; r;	})
    182 #  elif defined(__aarch64__)
    183 #   if defined(__BYTE_ORDER__)
    184 #    if defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
    185 #     define HOST_c2l(c,l)	({ uint32_t r;			\
    186 				   asm ("rev	%w0,%w1"	\
    187 					:"=r"(r)		\
    188 					:"r"(*((const uint32_t *)(c))));\
    189 				   (c)+=4; (l)=r;		})
    190 #     define HOST_l2c(l,c)	({ uint32_t r;			\
    191 				   asm ("rev	%w0,%w1"	\
    192 					:"=r"(r)		\
    193 					:"r"((uint32_t)(l)));	\
    194 				   *((uint32_t *)(c))=r; (c)+=4; r;	})
    195 #    elif defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
    196 #     define HOST_c2l(c,l)	(void)((l)=*((const uint32_t *)(c)), (c)+=4)
    197 #     define HOST_l2c(l,c)	(*((uint32_t *)(c))=(l), (c)+=4, (l))
    198 #    endif
    199 #   endif
    200 #  endif
    201 # endif
    202 #endif
    203 
    204 #ifndef HOST_c2l
    205 #define HOST_c2l(c,l)	(void)(l =(((uint32_t)(*((c)++)))<<24),	\
    206 			 l|=(((uint32_t)(*((c)++)))<<16),	\
    207 			 l|=(((uint32_t)(*((c)++)))<< 8),	\
    208 			 l|=(((uint32_t)(*((c)++)))    ))
    209 #endif
    210 #ifndef HOST_l2c
    211 #define HOST_l2c(l,c)	(*((c)++)=(uint8_t)(((l)>>24)&0xff),	\
    212 			 *((c)++)=(uint8_t)(((l)>>16)&0xff),	\
    213 			 *((c)++)=(uint8_t)(((l)>> 8)&0xff),	\
    214 			 *((c)++)=(uint8_t)(((l)    )&0xff),	\
    215 			 l)
    216 #endif
    217 
    218 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
    219 
    220 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
    221    /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
    222 #  define HOST_c2l(c,l)	(void)((l)=*((const uint32_t *)(c)), (c)+=4)
    223 #  define HOST_l2c(l,c)	(*((uint32_t *)(c))=(l), (c)+=4, l)
    224 #endif
    225 
    226 #ifndef HOST_c2l
    227 #define HOST_c2l(c,l)	(void)(l =(((uint32_t)(*((c)++)))    ),	\
    228 			 l|=(((uint32_t)(*((c)++)))<< 8),	\
    229 			 l|=(((uint32_t)(*((c)++)))<<16),	\
    230 			 l|=(((uint32_t)(*((c)++)))<<24))
    231 #endif
    232 #ifndef HOST_l2c
    233 #define HOST_l2c(l,c)	(*((c)++)=(uint8_t)(((l)    )&0xff),	\
    234 			 *((c)++)=(uint8_t)(((l)>> 8)&0xff),	\
    235 			 *((c)++)=(uint8_t)(((l)>>16)&0xff),	\
    236 			 *((c)++)=(uint8_t)(((l)>>24)&0xff),	\
    237 			 l)
    238 #endif
    239 
    240 #endif
    241 
    242 int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
    243 	{
    244 	const uint8_t *data=data_;
    245 	uint8_t *p;
    246 	HASH_LONG l;
    247 	size_t n;
    248 
    249 	if (len==0) return 1;
    250 
    251 	l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL;
    252 	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
    253 	 * Wei Dai <weidai (at) eskimo.com> for pointing it out. */
    254 	if (l < c->Nl) /* overflow */
    255 		c->Nh++;
    256 	c->Nh+=(HASH_LONG)(len>>29);	/* might cause compiler warning on 16-bit */
    257 	c->Nl=l;
    258 
    259 	n = c->num;
    260 	if (n != 0)
    261 		{
    262 		p=(uint8_t *)c->data;
    263 
    264 		if (len >= HASH_CBLOCK || len+n >= HASH_CBLOCK)
    265 			{
    266 			memcpy (p+n,data,HASH_CBLOCK-n);
    267 			HASH_BLOCK_DATA_ORDER (c,p,1);
    268 			n      = HASH_CBLOCK-n;
    269 			data  += n;
    270 			len   -= n;
    271 			c->num = 0;
    272 			memset (p,0,HASH_CBLOCK);	/* keep it zeroed */
    273 			}
    274 		else
    275 			{
    276 			memcpy (p+n,data,len);
    277 			c->num += (unsigned int)len;
    278 			return 1;
    279 			}
    280 		}
    281 
    282 	n = len/HASH_CBLOCK;
    283 	if (n > 0)
    284 		{
    285 		HASH_BLOCK_DATA_ORDER (c,data,n);
    286 		n    *= HASH_CBLOCK;
    287 		data += n;
    288 		len  -= n;
    289 		}
    290 
    291 	if (len != 0)
    292 		{
    293 		p = (uint8_t *)c->data;
    294 		c->num = (unsigned int)len;
    295 		memcpy (p,data,len);
    296 		}
    297 	return 1;
    298 	}
    299 
    300 
    301 void HASH_TRANSFORM (HASH_CTX *c, const uint8_t *data)
    302 	{
    303 	HASH_BLOCK_DATA_ORDER (c,data,1);
    304 	}
    305 
    306 
    307 int HASH_FINAL (uint8_t *md, HASH_CTX *c)
    308 	{
    309 	uint8_t *p = (uint8_t *)c->data;
    310 	size_t n = c->num;
    311 
    312 	p[n] = 0x80; /* there is always room for one */
    313 	n++;
    314 
    315 	if (n > (HASH_CBLOCK-8))
    316 		{
    317 		memset (p+n,0,HASH_CBLOCK-n);
    318 		n=0;
    319 		HASH_BLOCK_DATA_ORDER (c,p,1);
    320 		}
    321 	memset (p+n,0,HASH_CBLOCK-8-n);
    322 
    323 	p += HASH_CBLOCK-8;
    324 #if   defined(DATA_ORDER_IS_BIG_ENDIAN)
    325 	(void)HOST_l2c(c->Nh,p);
    326 	(void)HOST_l2c(c->Nl,p);
    327 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
    328 	(void)HOST_l2c(c->Nl,p);
    329 	(void)HOST_l2c(c->Nh,p);
    330 #endif
    331 	p -= HASH_CBLOCK;
    332 	HASH_BLOCK_DATA_ORDER (c,p,1);
    333 	c->num=0;
    334 	memset (p,0,HASH_CBLOCK);
    335 
    336 #ifndef HASH_MAKE_STRING
    337 #error "HASH_MAKE_STRING must be defined!"
    338 #else
    339 	HASH_MAKE_STRING(c,md);
    340 #endif
    341 
    342 	return 1;
    343 	}
    344 
    345 
    346 #if defined(__cplusplus)
    347 }  /* extern C */
    348 #endif
    349 
    350 #endif  /* OPENSSL_HEADER_MD32_COMMON_H */
    351