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