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