Eneboo - Documentación para desarrolladores
|
00001 /* crypto/md32_common.h */ 00002 /* ==================================================================== 00003 * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * 00017 * 3. All advertising materials mentioning features or use of this 00018 * software must display the following acknowledgment: 00019 * "This product includes software developed by the OpenSSL Project 00020 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 00021 * 00022 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 00023 * endorse or promote products derived from this software without 00024 * prior written permission. For written permission, please contact 00025 * licensing@OpenSSL.org. 00026 * 00027 * 5. Products derived from this software may not be called "OpenSSL" 00028 * nor may "OpenSSL" appear in their names without prior written 00029 * permission of the OpenSSL Project. 00030 * 00031 * 6. Redistributions of any form whatsoever must retain the following 00032 * acknowledgment: 00033 * "This product includes software developed by the OpenSSL Project 00034 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 00035 * 00036 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 00037 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00038 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00039 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 00040 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00041 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00042 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00043 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00044 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 00045 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00046 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 00047 * OF THE POSSIBILITY OF SUCH DAMAGE. 00048 * ==================================================================== 00049 * 00050 */ 00051 00052 /* 00053 * This is a generic 32 bit "collector" for message digest algorithms. 00054 * Whenever needed it collects input character stream into chunks of 00055 * 32 bit values and invokes a block function that performs actual hash 00056 * calculations. 00057 * 00058 * Porting guide. 00059 * 00060 * Obligatory macros: 00061 * 00062 * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN 00063 * this macro defines byte order of input stream. 00064 * HASH_CBLOCK 00065 * size of a unit chunk HASH_BLOCK operates on. 00066 * HASH_LONG 00067 * has to be at lest 32 bit wide, if it's wider, then 00068 * HASH_LONG_LOG2 *has to* be defined along 00069 * HASH_CTX 00070 * context structure that at least contains following 00071 * members: 00072 * typedef struct { 00073 * ... 00074 * HASH_LONG Nl,Nh; 00075 * either { 00076 * HASH_LONG data[HASH_LBLOCK]; 00077 * unsigned char data[HASH_CBLOCK]; 00078 * }; 00079 * unsigned int num; 00080 * ... 00081 * } HASH_CTX; 00082 * data[] vector is expected to be zeroed upon first call to 00083 * HASH_UPDATE. 00084 * HASH_UPDATE 00085 * name of "Update" function, implemented here. 00086 * HASH_TRANSFORM 00087 * name of "Transform" function, implemented here. 00088 * HASH_FINAL 00089 * name of "Final" function, implemented here. 00090 * HASH_BLOCK_DATA_ORDER 00091 * name of "block" function capable of treating *unaligned* input 00092 * message in original (data) byte order, implemented externally. 00093 * HASH_MAKE_STRING 00094 * macro convering context variables to an ASCII hash string. 00095 * 00096 * MD5 example: 00097 * 00098 * #define DATA_ORDER_IS_LITTLE_ENDIAN 00099 * 00100 * #define HASH_LONG MD5_LONG 00101 * #define HASH_LONG_LOG2 MD5_LONG_LOG2 00102 * #define HASH_CTX MD5_CTX 00103 * #define HASH_CBLOCK MD5_CBLOCK 00104 * #define HASH_UPDATE MD5_Update 00105 * #define HASH_TRANSFORM MD5_Transform 00106 * #define HASH_FINAL MD5_Final 00107 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order 00108 * 00109 * <appro@fy.chalmers.se> 00110 */ 00111 00112 #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) 00113 #error "DATA_ORDER must be defined!" 00114 #endif 00115 00116 #ifndef HASH_CBLOCK 00117 #error "HASH_CBLOCK must be defined!" 00118 #endif 00119 #ifndef HASH_LONG 00120 #error "HASH_LONG must be defined!" 00121 #endif 00122 #ifndef HASH_CTX 00123 #error "HASH_CTX must be defined!" 00124 #endif 00125 00126 #ifndef HASH_UPDATE 00127 #error "HASH_UPDATE must be defined!" 00128 #endif 00129 #ifndef HASH_TRANSFORM 00130 #error "HASH_TRANSFORM must be defined!" 00131 #endif 00132 #ifndef HASH_FINAL 00133 #error "HASH_FINAL must be defined!" 00134 #endif 00135 00136 #ifndef HASH_BLOCK_DATA_ORDER 00137 #error "HASH_BLOCK_DATA_ORDER must be defined!" 00138 #endif 00139 00140 /* 00141 * Engage compiler specific rotate intrinsic function if available. 00142 */ 00143 #undef ROTATE 00144 #ifndef PEDANTIC 00145 # if defined(_MSC_VER) || defined(__ICC) 00146 # define ROTATE(a,n) _lrotl(a,n) 00147 # elif defined(__MWERKS__) 00148 # if defined(__POWERPC__) 00149 # define ROTATE(a,n) __rlwinm(a,n,0,31) 00150 # elif defined(__MC68K__) 00151 /* Motorola specific tweak. <appro@fy.chalmers.se> */ 00152 # define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) ) 00153 # else 00154 # define ROTATE(a,n) __rol(a,n) 00155 # endif 00156 # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) 00157 /* 00158 * Some GNU C inline assembler templates. Note that these are 00159 * rotates by *constant* number of bits! But that's exactly 00160 * what we need here... 00161 * <appro@fy.chalmers.se> 00162 */ 00163 # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) 00164 # define ROTATE(a,n) ({ register unsigned int ret; \ 00165 asm ( \ 00166 "roll %1,%0" \ 00167 : "=r"(ret) \ 00168 : "I"(n), "0"(a) \ 00169 : "cc"); \ 00170 ret; \ 00171 }) 00172 # elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ 00173 defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__) 00174 # define ROTATE(a,n) ({ register unsigned int ret; \ 00175 asm ( \ 00176 "rlwinm %0,%1,%2,0,31" \ 00177 : "=r"(ret) \ 00178 : "r"(a), "I"(n)); \ 00179 ret; \ 00180 }) 00181 # elif defined(__s390x__) 00182 # define ROTATE(a,n) ({ register unsigned int ret; \ 00183 asm ("rll %0,%1,%2" \ 00184 : "=r"(ret) \ 00185 : "r"(a), "I"(n)); \ 00186 ret; \ 00187 }) 00188 # endif 00189 # endif 00190 #endif /* PEDANTIC */ 00191 00192 #ifndef ROTATE 00193 #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) 00194 #endif 00195 00196 #if defined(DATA_ORDER_IS_BIG_ENDIAN) 00197 00198 #ifndef PEDANTIC 00199 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) 00200 # if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \ 00201 (defined(__x86_64) || defined(__x86_64__)) 00202 # if !defined(B_ENDIAN) 00203 /* 00204 * This gives ~30-40% performance improvement in SHA-256 compiled 00205 * with gcc [on P4]. Well, first macro to be frank. We can pull 00206 * this trick on x86* platforms only, because these CPUs can fetch 00207 * unaligned data without raising an exception. 00208 */ 00209 # define HOST_c2l(c,l) ({ unsigned int r=*((const unsigned int *)(c)); \ 00210 asm ("bswapl %0":"=r"(r):"0"(r)); \ 00211 (c)+=4; (l)=r; }) 00212 # define HOST_l2c(l,c) ({ unsigned int r=(l); \ 00213 asm ("bswapl %0":"=r"(r):"0"(r)); \ 00214 *((unsigned int *)(c))=r; (c)+=4; r; }) 00215 # endif 00216 # endif 00217 # endif 00218 #endif 00219 #if defined(__s390__) || defined(__s390x__) 00220 # define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l)) 00221 # define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l)) 00222 #endif 00223 00224 #ifndef HOST_c2l 00225 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ 00226 l|=(((unsigned long)(*((c)++)))<<16), \ 00227 l|=(((unsigned long)(*((c)++)))<< 8), \ 00228 l|=(((unsigned long)(*((c)++))) ), \ 00229 l) 00230 #endif 00231 #ifndef HOST_l2c 00232 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ 00233 *((c)++)=(unsigned char)(((l)>>16)&0xff), \ 00234 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ 00235 *((c)++)=(unsigned char)(((l) )&0xff), \ 00236 l) 00237 #endif 00238 00239 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) 00240 00241 #ifndef PEDANTIC 00242 # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) 00243 # if defined(__s390x__) 00244 # define HOST_c2l(c,l) ({ asm ("lrv %0,%1" \ 00245 :"=d"(l) :"m"(*(const unsigned int *)(c)));\ 00246 (c)+=4; (l); }) 00247 # define HOST_l2c(l,c) ({ asm ("strv %1,%0" \ 00248 :"=m"(*(unsigned int *)(c)) :"d"(l));\ 00249 (c)+=4; (l); }) 00250 # endif 00251 # endif 00252 #endif 00253 #if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) 00254 # ifndef B_ENDIAN 00255 /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */ 00256 # define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, l) 00257 # define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, l) 00258 # endif 00259 #endif 00260 00261 #ifndef HOST_c2l 00262 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ 00263 l|=(((unsigned long)(*((c)++)))<< 8), \ 00264 l|=(((unsigned long)(*((c)++)))<<16), \ 00265 l|=(((unsigned long)(*((c)++)))<<24), \ 00266 l) 00267 #endif 00268 #ifndef HOST_l2c 00269 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ 00270 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ 00271 *((c)++)=(unsigned char)(((l)>>16)&0xff), \ 00272 *((c)++)=(unsigned char)(((l)>>24)&0xff), \ 00273 l) 00274 #endif 00275 00276 #endif 00277 00278 /* 00279 * Time for some action:-) 00280 */ 00281 00282 int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len) 00283 { 00284 const unsigned char *data=data_; 00285 unsigned char *p; 00286 HASH_LONG l; 00287 size_t n; 00288 00289 if (len==0) return 1; 00290 00291 l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL; 00292 /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to 00293 * Wei Dai <weidai@eskimo.com> for pointing it out. */ 00294 if (l < c->Nl) /* overflow */ 00295 c->Nh++; 00296 c->Nh+=(len>>29); /* might cause compiler warning on 16-bit */ 00297 c->Nl=l; 00298 00299 n = c->num; 00300 if (n != 0) 00301 { 00302 p=(unsigned char *)c->data; 00303 00304 if (len >= HASH_CBLOCK || len+n >= HASH_CBLOCK) 00305 { 00306 memcpy (p+n,data,HASH_CBLOCK-n); 00307 HASH_BLOCK_DATA_ORDER (c,p,1); 00308 n = HASH_CBLOCK-n; 00309 data += n; 00310 len -= n; 00311 c->num = 0; 00312 memset (p,0,HASH_CBLOCK); /* keep it zeroed */ 00313 } 00314 else 00315 { 00316 memcpy (p+n,data,len); 00317 c->num += (unsigned int)len; 00318 return 1; 00319 } 00320 } 00321 00322 n = len/HASH_CBLOCK; 00323 if (n > 0) 00324 { 00325 HASH_BLOCK_DATA_ORDER (c,data,n); 00326 n *= HASH_CBLOCK; 00327 data += n; 00328 len -= n; 00329 } 00330 00331 if (len != 0) 00332 { 00333 p = (unsigned char *)c->data; 00334 c->num = len; 00335 memcpy (p,data,len); 00336 } 00337 return 1; 00338 } 00339 00340 00341 void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) 00342 { 00343 HASH_BLOCK_DATA_ORDER (c,data,1); 00344 } 00345 00346 00347 int HASH_FINAL (unsigned char *md, HASH_CTX *c) 00348 { 00349 unsigned char *p = (unsigned char *)c->data; 00350 size_t n = c->num; 00351 00352 p[n] = 0x80; /* there is always room for one */ 00353 n++; 00354 00355 if (n > (HASH_CBLOCK-8)) 00356 { 00357 memset (p+n,0,HASH_CBLOCK-n); 00358 n=0; 00359 HASH_BLOCK_DATA_ORDER (c,p,1); 00360 } 00361 memset (p+n,0,HASH_CBLOCK-8-n); 00362 00363 p += HASH_CBLOCK-8; 00364 #if defined(DATA_ORDER_IS_BIG_ENDIAN) 00365 (void)HOST_l2c(c->Nh,p); 00366 (void)HOST_l2c(c->Nl,p); 00367 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) 00368 (void)HOST_l2c(c->Nl,p); 00369 (void)HOST_l2c(c->Nh,p); 00370 #endif 00371 p -= HASH_CBLOCK; 00372 HASH_BLOCK_DATA_ORDER (c,p,1); 00373 c->num=0; 00374 memset (p,0,HASH_CBLOCK); 00375 00376 #ifndef HASH_MAKE_STRING 00377 #error "HASH_MAKE_STRING must be defined!" 00378 #else 00379 HASH_MAKE_STRING(c,md); 00380 #endif 00381 00382 return 1; 00383 } 00384 00385 #ifndef MD32_REG_T 00386 #define MD32_REG_T long 00387 /* 00388 * This comment was originaly written for MD5, which is why it 00389 * discusses A-D. But it basically applies to all 32-bit digests, 00390 * which is why it was moved to common header file. 00391 * 00392 * In case you wonder why A-D are declared as long and not 00393 * as MD5_LONG. Doing so results in slight performance 00394 * boost on LP64 architectures. The catch is we don't 00395 * really care if 32 MSBs of a 64-bit register get polluted 00396 * with eventual overflows as we *save* only 32 LSBs in 00397 * *either* case. Now declaring 'em long excuses the compiler 00398 * from keeping 32 MSBs zeroed resulting in 13% performance 00399 * improvement under SPARC Solaris7/64 and 5% under AlphaLinux. 00400 * Well, to be honest it should say that this *prevents* 00401 * performance degradation. 00402 * <appro@fy.chalmers.se> 00403 * Apparently there're LP64 compilers that generate better 00404 * code if A-D are declared int. Most notably GCC-x86_64 00405 * generates better code. 00406 * <appro@fy.chalmers.se> 00407 */ 00408 #endif