Branch data Line data Source code
1 : : /* crypto/md32_common.h */
2 : : /* ====================================================================
3 : : * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
4 : : *
5 : : * Redistribution and use in source and binary forms, with or without
6 : : * modification, are permitted provided that the following conditions
7 : : * are met:
8 : : *
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : *
12 : : * 2. Redistributions in binary form must reproduce the above copyright
13 : : * notice, this list of conditions and the following disclaimer in
14 : : * the documentation and/or other materials provided with the
15 : : * distribution.
16 : : *
17 : : * 3. All advertising materials mentioning features or use of this
18 : : * software must display the following acknowledgment:
19 : : * "This product includes software developed by the OpenSSL Project
20 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21 : : *
22 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 : : * endorse or promote products derived from this software without
24 : : * prior written permission. For written permission, please contact
25 : : * licensing@OpenSSL.org.
26 : : *
27 : : * 5. Products derived from this software may not be called "OpenSSL"
28 : : * nor may "OpenSSL" appear in their names without prior written
29 : : * permission of the OpenSSL Project.
30 : : *
31 : : * 6. Redistributions of any form whatsoever must retain the following
32 : : * acknowledgment:
33 : : * "This product includes software developed by the OpenSSL Project
34 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35 : : *
36 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
48 : : * ====================================================================
49 : : *
50 : : */
51 : :
52 : : /*
53 : : * This is a generic 32 bit "collector" for message digest algorithms.
54 : : * Whenever needed it collects input character stream into chunks of
55 : : * 32 bit values and invokes a block function that performs actual hash
56 : : * calculations.
57 : : *
58 : : * Porting guide.
59 : : *
60 : : * Obligatory macros:
61 : : *
62 : : * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
63 : : * this macro defines byte order of input stream.
64 : : * HASH_CBLOCK
65 : : * size of a unit chunk HASH_BLOCK operates on.
66 : : * HASH_LONG
67 : : * has to be at lest 32 bit wide, if it's wider, then
68 : : * HASH_LONG_LOG2 *has to* be defined along
69 : : * HASH_CTX
70 : : * context structure that at least contains following
71 : : * members:
72 : : * typedef struct {
73 : : * ...
74 : : * HASH_LONG Nl,Nh;
75 : : * either {
76 : : * HASH_LONG data[HASH_LBLOCK];
77 : : * unsigned char data[HASH_CBLOCK];
78 : : * };
79 : : * unsigned int num;
80 : : * ...
81 : : * } HASH_CTX;
82 : : * data[] vector is expected to be zeroed upon first call to
83 : : * HASH_UPDATE.
84 : : * HASH_UPDATE
85 : : * name of "Update" function, implemented here.
86 : : * HASH_TRANSFORM
87 : : * name of "Transform" function, implemented here.
88 : : * HASH_FINAL
89 : : * name of "Final" function, implemented here.
90 : : * HASH_BLOCK_DATA_ORDER
91 : : * name of "block" function capable of treating *unaligned* input
92 : : * message in original (data) byte order, implemented externally.
93 : : * HASH_MAKE_STRING
94 : : * macro convering context variables to an ASCII hash string.
95 : : *
96 : : * MD5 example:
97 : : *
98 : : * #define DATA_ORDER_IS_LITTLE_ENDIAN
99 : : *
100 : : * #define HASH_LONG MD5_LONG
101 : : * #define HASH_LONG_LOG2 MD5_LONG_LOG2
102 : : * #define HASH_CTX MD5_CTX
103 : : * #define HASH_CBLOCK MD5_CBLOCK
104 : : * #define HASH_UPDATE MD5_Update
105 : : * #define HASH_TRANSFORM MD5_Transform
106 : : * #define HASH_FINAL MD5_Final
107 : : * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
108 : : *
109 : : * <appro@fy.chalmers.se>
110 : : */
111 : :
112 : : #if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
113 : : #error "DATA_ORDER must be defined!"
114 : : #endif
115 : :
116 : : #ifndef HASH_CBLOCK
117 : : #error "HASH_CBLOCK must be defined!"
118 : : #endif
119 : : #ifndef HASH_LONG
120 : : #error "HASH_LONG must be defined!"
121 : : #endif
122 : : #ifndef HASH_CTX
123 : : #error "HASH_CTX must be defined!"
124 : : #endif
125 : :
126 : : #ifndef HASH_UPDATE
127 : : #error "HASH_UPDATE must be defined!"
128 : : #endif
129 : : #ifndef HASH_TRANSFORM
130 : : #error "HASH_TRANSFORM must be defined!"
131 : : #endif
132 : : #ifndef HASH_FINAL
133 : : #error "HASH_FINAL must be defined!"
134 : : #endif
135 : :
136 : : #ifndef HASH_BLOCK_DATA_ORDER
137 : : #error "HASH_BLOCK_DATA_ORDER must be defined!"
138 : : #endif
139 : :
140 : : /*
141 : : * Engage compiler specific rotate intrinsic function if available.
142 : : */
143 : : #undef ROTATE
144 : : #ifndef PEDANTIC
145 : : # if defined(_MSC_VER)
146 : : # define ROTATE(a,n) _lrotl(a,n)
147 : : # elif defined(__ICC)
148 : : # define ROTATE(a,n) _rotl(a,n)
149 : : # elif defined(__MWERKS__)
150 : : # if defined(__POWERPC__)
151 : : # define ROTATE(a,n) __rlwinm(a,n,0,31)
152 : : # elif defined(__MC68K__)
153 : : /* Motorola specific tweak. <appro@fy.chalmers.se> */
154 : : # define ROTATE(a,n) ( n<24 ? __rol(a,n) : __ror(a,32-n) )
155 : : # else
156 : : # define ROTATE(a,n) __rol(a,n)
157 : : # endif
158 : : # elif defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
159 : : /*
160 : : * Some GNU C inline assembler templates. Note that these are
161 : : * rotates by *constant* number of bits! But that's exactly
162 : : * what we need here...
163 : : * <appro@fy.chalmers.se>
164 : : */
165 : : # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
166 : : # define ROTATE(a,n) ({ register unsigned int ret; \
167 : : asm ( \
168 : : "roll %1,%0" \
169 : : : "=r"(ret) \
170 : : : "I"(n), "0"((unsigned int)(a)) \
171 : : : "cc"); \
172 : : ret; \
173 : : })
174 : : # elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
175 : : defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__)
176 : : # define ROTATE(a,n) ({ register unsigned int ret; \
177 : : asm ( \
178 : : "rlwinm %0,%1,%2,0,31" \
179 : : : "=r"(ret) \
180 : : : "r"(a), "I"(n)); \
181 : : ret; \
182 : : })
183 : : # elif defined(__s390x__)
184 : : # define ROTATE(a,n) ({ register unsigned int ret; \
185 : : asm ("rll %0,%1,%2" \
186 : : : "=r"(ret) \
187 : : : "r"(a), "I"(n)); \
188 : : ret; \
189 : : })
190 : : # endif
191 : : # endif
192 : : #endif /* PEDANTIC */
193 : :
194 : : #ifndef ROTATE
195 : : #define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
196 : : #endif
197 : :
198 : : #if defined(DATA_ORDER_IS_BIG_ENDIAN)
199 : :
200 : : #ifndef PEDANTIC
201 : : # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
202 : : # if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \
203 : : (defined(__x86_64) || defined(__x86_64__))
204 : : # if !defined(B_ENDIAN)
205 : : /*
206 : : * This gives ~30-40% performance improvement in SHA-256 compiled
207 : : * with gcc [on P4]. Well, first macro to be frank. We can pull
208 : : * this trick on x86* platforms only, because these CPUs can fetch
209 : : * unaligned data without raising an exception.
210 : : */
211 : : # define HOST_c2l(c,l) ({ unsigned int r=*((const unsigned int *)(c)); \
212 : : asm ("bswapl %0":"=r"(r):"0"(r)); \
213 : : (c)+=4; (l)=r; })
214 : : # define HOST_l2c(l,c) ({ unsigned int r=(l); \
215 : : asm ("bswapl %0":"=r"(r):"0"(r)); \
216 : : *((unsigned int *)(c))=r; (c)+=4; r; })
217 : : # endif
218 : : # elif defined(__aarch64__)
219 : : # if defined(__BYTE_ORDER__)
220 : : # if defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
221 : : # define HOST_c2l(c,l) ({ unsigned int r; \
222 : : asm ("rev %w0,%w1" \
223 : : :"=r"(r) \
224 : : :"r"(*((const unsigned int *)(c))));\
225 : : (c)+=4; (l)=r; })
226 : : # define HOST_l2c(l,c) ({ unsigned int r; \
227 : : asm ("rev %w0,%w1" \
228 : : :"=r"(r) \
229 : : :"r"((unsigned int)(l)));\
230 : : *((unsigned int *)(c))=r; (c)+=4; r; })
231 : : # elif defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
232 : : # define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l))
233 : : # define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l))
234 : : # endif
235 : : # endif
236 : : # endif
237 : : # endif
238 : : # if defined(__s390__) || defined(__s390x__)
239 : : # define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, (l))
240 : : # define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, (l))
241 : : # endif
242 : : #endif
243 : :
244 : : #ifndef HOST_c2l
245 : : #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
246 : : l|=(((unsigned long)(*((c)++)))<<16), \
247 : : l|=(((unsigned long)(*((c)++)))<< 8), \
248 : : l|=(((unsigned long)(*((c)++))) ), \
249 : : l)
250 : : #endif
251 : : #ifndef HOST_l2c
252 : : #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
253 : : *((c)++)=(unsigned char)(((l)>>16)&0xff), \
254 : : *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
255 : : *((c)++)=(unsigned char)(((l) )&0xff), \
256 : : l)
257 : : #endif
258 : :
259 : : #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
260 : :
261 : : #ifndef PEDANTIC
262 : : # if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
263 : : # if defined(__s390x__)
264 : : # define HOST_c2l(c,l) ({ asm ("lrv %0,%1" \
265 : : :"=d"(l) :"m"(*(const unsigned int *)(c)));\
266 : : (c)+=4; (l); })
267 : : # define HOST_l2c(l,c) ({ asm ("strv %1,%0" \
268 : : :"=m"(*(unsigned int *)(c)) :"d"(l));\
269 : : (c)+=4; (l); })
270 : : # endif
271 : : # endif
272 : : # if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
273 : : # ifndef B_ENDIAN
274 : : /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
275 : : # define HOST_c2l(c,l) ((l)=*((const unsigned int *)(c)), (c)+=4, l)
276 : : # define HOST_l2c(l,c) (*((unsigned int *)(c))=(l), (c)+=4, l)
277 : : # endif
278 : : # endif
279 : : #endif
280 : :
281 : : #ifndef HOST_c2l
282 : : #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
283 : : l|=(((unsigned long)(*((c)++)))<< 8), \
284 : : l|=(((unsigned long)(*((c)++)))<<16), \
285 : : l|=(((unsigned long)(*((c)++)))<<24), \
286 : : l)
287 : : #endif
288 : : #ifndef HOST_l2c
289 : : #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
290 : : *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
291 : : *((c)++)=(unsigned char)(((l)>>16)&0xff), \
292 : : *((c)++)=(unsigned char)(((l)>>24)&0xff), \
293 : : l)
294 : : #endif
295 : :
296 : : #endif
297 : :
298 : : /*
299 : : * Time for some action:-)
300 : : */
301 : :
302 : 6874519 : int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
303 : : {
304 : 6874519 : const unsigned char *data=data_;
305 : : unsigned char *p;
306 : : HASH_LONG l;
307 : : size_t n;
308 : :
309 [ + + ]: 6874519 : if (len==0) return 1;
310 : :
311 : 6873681 : l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL;
312 : : /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
313 : : * Wei Dai <weidai@eskimo.com> for pointing it out. */
314 [ - + ]: 6873681 : if (l < c->Nl) /* overflow */
315 : 0 : c->Nh++;
316 : 6873681 : c->Nh+=(HASH_LONG)(len>>29); /* might cause compiler warning on 16-bit */
317 : 6873681 : c->Nl=l;
318 : :
319 : 6873681 : n = c->num;
320 [ + + ]: 6873681 : if (n != 0)
321 : : {
322 : 5441447 : p=(unsigned char *)c->data;
323 : :
324 [ + + ][ + + ]: 5441447 : if (len >= HASH_CBLOCK || len+n >= HASH_CBLOCK)
325 : : {
326 : 496866 : memcpy (p+n,data,HASH_CBLOCK-n);
327 : 496866 : HASH_BLOCK_DATA_ORDER (c,p,1);
328 : 496866 : n = HASH_CBLOCK-n;
329 : 496866 : data += n;
330 : 496866 : len -= n;
331 : 496866 : c->num = 0;
332 : : memset (p,0,HASH_CBLOCK); /* keep it zeroed */
333 : : }
334 : : else
335 : : {
336 : 4944581 : memcpy (p+n,data,len);
337 : 4944581 : c->num += (unsigned int)len;
338 : 4944581 : return 1;
339 : : }
340 : : }
341 : :
342 : 1929100 : n = len/HASH_CBLOCK;
343 [ + + ]: 1929100 : if (n > 0)
344 : : {
345 : 99725 : HASH_BLOCK_DATA_ORDER (c,data,n);
346 : 99725 : n *= HASH_CBLOCK;
347 : 99725 : data += n;
348 : 99725 : len -= n;
349 : : }
350 : :
351 [ + + ]: 1929100 : if (len != 0)
352 : : {
353 : 1872764 : p = (unsigned char *)c->data;
354 : 1872764 : c->num = (unsigned int)len;
355 : : memcpy (p,data,len);
356 : : }
357 : : return 1;
358 : : }
359 : :
360 : :
361 : 5148 : void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
362 : : {
363 : 5148 : HASH_BLOCK_DATA_ORDER (c,data,1);
364 : 5148 : }
365 : :
366 : :
367 : 1408815 : int HASH_FINAL (unsigned char *md, HASH_CTX *c)
368 : : {
369 : 1408815 : unsigned char *p = (unsigned char *)c->data;
370 : 1408815 : size_t n = c->num;
371 : :
372 : 1408815 : p[n] = 0x80; /* there is always room for one */
373 : 1408815 : n++;
374 : :
375 [ + + ]: 1408815 : if (n > (HASH_CBLOCK-8))
376 : : {
377 : 555269 : memset (p+n,0,HASH_CBLOCK-n);
378 : 555269 : n=0;
379 : 555269 : HASH_BLOCK_DATA_ORDER (c,p,1);
380 : : }
381 : 1408815 : memset (p+n,0,HASH_CBLOCK-8-n);
382 : :
383 : 1408815 : p += HASH_CBLOCK-8;
384 : : #if defined(DATA_ORDER_IS_BIG_ENDIAN)
385 : 1316498 : (void)HOST_l2c(c->Nh,p);
386 : 1316498 : (void)HOST_l2c(c->Nl,p);
387 : : #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
388 : 92317 : (void)HOST_l2c(c->Nl,p);
389 : 92317 : (void)HOST_l2c(c->Nh,p);
390 : : #endif
391 : 1408815 : p -= HASH_CBLOCK;
392 : 1408815 : HASH_BLOCK_DATA_ORDER (c,p,1);
393 : 1408815 : c->num=0;
394 : : memset (p,0,HASH_CBLOCK);
395 : :
396 : : #ifndef HASH_MAKE_STRING
397 : : #error "HASH_MAKE_STRING must be defined!"
398 : : #else
399 [ + + - ]: 1881580 : HASH_MAKE_STRING(c,md);
[ + + ][ + + ]
[ # # ][ # # ]
400 : : #endif
401 : :
402 : 1349719 : return 1;
403 : : }
404 : :
405 : : #ifndef MD32_REG_T
406 : : #if defined(__alpha) || defined(__sparcv9) || defined(__mips)
407 : : #define MD32_REG_T long
408 : : /*
409 : : * This comment was originaly written for MD5, which is why it
410 : : * discusses A-D. But it basically applies to all 32-bit digests,
411 : : * which is why it was moved to common header file.
412 : : *
413 : : * In case you wonder why A-D are declared as long and not
414 : : * as MD5_LONG. Doing so results in slight performance
415 : : * boost on LP64 architectures. The catch is we don't
416 : : * really care if 32 MSBs of a 64-bit register get polluted
417 : : * with eventual overflows as we *save* only 32 LSBs in
418 : : * *either* case. Now declaring 'em long excuses the compiler
419 : : * from keeping 32 MSBs zeroed resulting in 13% performance
420 : : * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
421 : : * Well, to be honest it should say that this *prevents*
422 : : * performance degradation.
423 : : * <appro@fy.chalmers.se>
424 : : */
425 : : #else
426 : : /*
427 : : * Above is not absolute and there are LP64 compilers that
428 : : * generate better code if MD32_REG_T is defined int. The above
429 : : * pre-processor condition reflects the circumstances under which
430 : : * the conclusion was made and is subject to further extension.
431 : : * <appro@fy.chalmers.se>
432 : : */
433 : : #define MD32_REG_T int
434 : : #endif
435 : : #endif
|