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@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) 56extern "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 lest 32 bit wide, if it's wider, then 76 * HASH_LONG_LOG2 *has to* be defined along 77 * HASH_CTX 78 * context structure that at least contains following 79 * members: 80 * typedef struct { 81 * ... 82 * HASH_LONG Nl,Nh; 83 * either { 84 * HASH_LONG data[HASH_LBLOCK]; 85 * unsigned char data[HASH_CBLOCK]; 86 * }; 87 * unsigned int num; 88 * ... 89 * } HASH_CTX; 90 * data[] vector is expected to be zeroed upon first call to 91 * HASH_UPDATE. 92 * HASH_UPDATE 93 * name of "Update" function, implemented here. 94 * HASH_TRANSFORM 95 * name of "Transform" function, implemented here. 96 * HASH_FINAL 97 * name of "Final" function, implemented here. 98 * HASH_BLOCK_DATA_ORDER 99 * name of "block" function capable of treating *unaligned* input 100 * message in original (data) byte order, implemented externally. 101 * HASH_MAKE_STRING 102 * macro convering context variables to an ASCII hash string. 103 * 104 * MD5 example: 105 * 106 * #define DATA_ORDER_IS_LITTLE_ENDIAN 107 * 108 * #define HASH_LONG MD5_LONG 109 * #define HASH_LONG_LOG2 MD5_LONG_LOG2 110 * #define HASH_CTX MD5_CTX 111 * #define HASH_CBLOCK MD5_CBLOCK 112 * #define HASH_UPDATE MD5_Update 113 * #define HASH_TRANSFORM MD5_Transform 114 * #define HASH_FINAL MD5_Final 115 * #define HASH_BLOCK_DATA_ORDER md5_block_data_order 116 * 117 * <appro@fy.chalmers.se> 118 */ 119 120#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN) 121#error "DATA_ORDER must be defined!" 122#endif 123 124#ifndef HASH_CBLOCK 125#error "HASH_CBLOCK must be defined!" 126#endif 127#ifndef HASH_LONG 128#error "HASH_LONG must be defined!" 129#endif 130#ifndef HASH_CTX 131#error "HASH_CTX must be defined!" 132#endif 133 134#ifndef HASH_UPDATE 135#error "HASH_UPDATE must be defined!" 136#endif 137#ifndef HASH_TRANSFORM 138#error "HASH_TRANSFORM must be defined!" 139#endif 140#ifndef HASH_FINAL 141#error "HASH_FINAL must be defined!" 142#endif 143 144#ifndef HASH_BLOCK_DATA_ORDER 145#error "HASH_BLOCK_DATA_ORDER must be defined!" 146#endif 147 148/* 149 * Engage compiler specific rotate intrinsic function if available. 150 */ 151#undef ROTATE 152# if defined(_MSC_VER) 153# define ROTATE(a,n) _lrotl(a,n) 154# elif defined(__ICC) 155# define ROTATE(a,n) _rotl(a,n) 156# elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) 157 /* 158 * Some GNU C inline assembler templates. Note that these are 159 * rotates by *constant* number of bits! But that's exactly 160 * what we need here... 161 * <appro@fy.chalmers.se> 162 */ 163# if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) 164# define ROTATE(a,n) ({ register unsigned int ret; \ 165 asm ( \ 166 "roll %1,%0" \ 167 : "=r"(ret) \ 168 : "I"(n), "0"((unsigned int)(a)) \ 169 : "cc"); \ 170 ret; \ 171 }) 172# endif /* OPENSSL_X86 || OPENSSL_X86_64 */ 173# endif /* COMPILER */ 174 175#ifndef ROTATE 176#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) 177#endif 178 179#if defined(DATA_ORDER_IS_BIG_ENDIAN) 180 181#ifndef PEDANTIC 182# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) 183# if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) 184 /* 185 * This gives ~30-40% performance improvement in SHA-256 compiled 186 * with gcc [on P4]. Well, first macro to be frank. We can pull 187 * this trick on x86* platforms only, because these CPUs can fetch 188 * unaligned data without raising an exception. 189 */ 190# define HOST_c2l(c,l) ({ unsigned int r=*((const unsigned int *)(c)); \ 191 asm ("bswapl %0":"=r"(r):"0"(r)); \ 192 (c)+=4; (l)=r; }) 193# define HOST_l2c(l,c) ({ unsigned int r=(l); \ 194 asm ("bswapl %0":"=r"(r):"0"(r)); \ 195 *((unsigned int *)(c))=r; (c)+=4; r; }) 196# elif defined(__aarch64__) 197# if defined(__BYTE_ORDER__) 198# if defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ 199# define HOST_c2l(c,l) ({ unsigned int r; \ 200 asm ("rev %w0,%w1" \ 201 :"=r"(r) \ 202 :"r"(*((const unsigned int *)(c))));\ 203 (c)+=4; (l)=r; }) 204# define HOST_l2c(l,c) ({ unsigned int r; \ 205 asm ("rev %w0,%w1" \ 206 :"=r"(r) \ 207 :"r"((unsigned int)(l)));\ 208 *((unsigned int *)(c))=r; (c)+=4; r; }) 209# elif defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ 210# define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l)) 211# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l)) 212# endif 213# endif 214# endif 215# endif 216#endif 217 218#ifndef HOST_c2l 219#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ 220 l|=(((unsigned long)(*((c)++)))<<16), \ 221 l|=(((unsigned long)(*((c)++)))<< 8), \ 222 l|=(((unsigned long)(*((c)++))) ), \ 223 l) 224#endif 225#ifndef HOST_l2c 226#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ 227 *((c)++)=(unsigned char)(((l)>>16)&0xff), \ 228 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ 229 *((c)++)=(unsigned char)(((l) )&0xff), \ 230 l) 231#endif 232 233#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) 234 235#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) 236 /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */ 237# define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, l) 238# define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, l) 239#endif 240 241#ifndef HOST_c2l 242#define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ 243 l|=(((unsigned long)(*((c)++)))<< 8), \ 244 l|=(((unsigned long)(*((c)++)))<<16), \ 245 l|=(((unsigned long)(*((c)++)))<<24), \ 246 l) 247#endif 248#ifndef HOST_l2c 249#define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ 250 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ 251 *((c)++)=(unsigned char)(((l)>>16)&0xff), \ 252 *((c)++)=(unsigned char)(((l)>>24)&0xff), \ 253 l) 254#endif 255 256#endif 257 258int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len) 259 { 260 const unsigned char *data=data_; 261 unsigned char *p; 262 HASH_LONG l; 263 size_t n; 264 265 if (len==0) return 1; 266 267 l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL; 268 /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to 269 * Wei Dai <weidai@eskimo.com> for pointing it out. */ 270 if (l < c->Nl) /* overflow */ 271 c->Nh++; 272 c->Nh+=(HASH_LONG)(len>>29); /* might cause compiler warning on 16-bit */ 273 c->Nl=l; 274 275 n = c->num; 276 if (n != 0) 277 { 278 p=(unsigned char *)c->data; 279 280 if (len >= HASH_CBLOCK || len+n >= HASH_CBLOCK) 281 { 282 memcpy (p+n,data,HASH_CBLOCK-n); 283 HASH_BLOCK_DATA_ORDER (c,p,1); 284 n = HASH_CBLOCK-n; 285 data += n; 286 len -= n; 287 c->num = 0; 288 memset (p,0,HASH_CBLOCK); /* keep it zeroed */ 289 } 290 else 291 { 292 memcpy (p+n,data,len); 293 c->num += (unsigned int)len; 294 return 1; 295 } 296 } 297 298 n = len/HASH_CBLOCK; 299 if (n > 0) 300 { 301 HASH_BLOCK_DATA_ORDER (c,data,n); 302 n *= HASH_CBLOCK; 303 data += n; 304 len -= n; 305 } 306 307 if (len != 0) 308 { 309 p = (unsigned char *)c->data; 310 c->num = (unsigned int)len; 311 memcpy (p,data,len); 312 } 313 return 1; 314 } 315 316 317void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data) 318 { 319 HASH_BLOCK_DATA_ORDER (c,data,1); 320 } 321 322 323int HASH_FINAL (unsigned char *md, HASH_CTX *c) 324 { 325 unsigned char *p = (unsigned char *)c->data; 326 size_t n = c->num; 327 328 p[n] = 0x80; /* there is always room for one */ 329 n++; 330 331 if (n > (HASH_CBLOCK-8)) 332 { 333 memset (p+n,0,HASH_CBLOCK-n); 334 n=0; 335 HASH_BLOCK_DATA_ORDER (c,p,1); 336 } 337 memset (p+n,0,HASH_CBLOCK-8-n); 338 339 p += HASH_CBLOCK-8; 340#if defined(DATA_ORDER_IS_BIG_ENDIAN) 341 (void)HOST_l2c(c->Nh,p); 342 (void)HOST_l2c(c->Nl,p); 343#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) 344 (void)HOST_l2c(c->Nl,p); 345 (void)HOST_l2c(c->Nh,p); 346#endif 347 p -= HASH_CBLOCK; 348 HASH_BLOCK_DATA_ORDER (c,p,1); 349 c->num=0; 350 memset (p,0,HASH_CBLOCK); 351 352#ifndef HASH_MAKE_STRING 353#error "HASH_MAKE_STRING must be defined!" 354#else 355 HASH_MAKE_STRING(c,md); 356#endif 357 358 return 1; 359 } 360 361#ifndef MD32_REG_T 362#define MD32_REG_T int 363#endif 364 365 366#if defined(__cplusplus) 367} /* extern C */ 368#endif 369 370#endif /* OPENSSL_HEADER_MD32_COMMON_H */ 371