Rid the world of yet more evil casts.
[oweals/openssl.git] / crypto / md5 / md5_dgst.c
1 /* crypto/md5/md5_dgst.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include "md5_locl.h"
61 #include "opensslv.h"
62
63 char *MD5_version="MD5" OPENSSL_VERSION_PTEXT;
64
65 /* Implemented from RFC1321 The MD5 Message-Digest Algorithm
66  */
67
68 #define INIT_DATA_A (unsigned long)0x67452301L
69 #define INIT_DATA_B (unsigned long)0xefcdab89L
70 #define INIT_DATA_C (unsigned long)0x98badcfeL
71 #define INIT_DATA_D (unsigned long)0x10325476L
72
73 #ifndef NOPROTO
74 #  ifdef MD5_ASM
75      void md5_block_x86(MD5_CTX *c, unsigned long *p,int num);
76 #    define md5_block md5_block_x86
77 #  else
78      static void md5_block(MD5_CTX *c, unsigned long *p,int num);
79 #  endif
80 #else
81 #  ifdef MD5_ASM
82      void md5_block_x86();
83 #    define md5_block md5_block_x86
84 #  else
85      static void md5_block();
86 #  endif
87 #endif
88
89 void MD5_Init(c)
90 MD5_CTX *c;
91         {
92         c->A=INIT_DATA_A;
93         c->B=INIT_DATA_B;
94         c->C=INIT_DATA_C;
95         c->D=INIT_DATA_D;
96         c->Nl=0;
97         c->Nh=0;
98         c->num=0;
99         }
100
101 void MD5_Update(c, _data, len)
102 MD5_CTX *c;
103 const void *_data;
104 unsigned long len;
105         {
106         register const unsigned char *data=_data;
107         register ULONG *p;
108         int sw,sc;
109         ULONG l;
110
111         if (len == 0) return;
112
113         l=(c->Nl+(len<<3))&0xffffffffL;
114         /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
115          * Wei Dai <weidai@eskimo.com> for pointing it out. */
116         if (l < c->Nl) /* overflow */
117                 c->Nh++;
118         c->Nh+=(len>>29);
119         c->Nl=l;
120
121         if (c->num != 0)
122                 {
123                 p=c->data;
124                 sw=c->num>>2;
125                 sc=c->num&0x03;
126
127                 if ((c->num+len) >= MD5_CBLOCK)
128                         {
129                         l= p[sw];
130                         p_c2l(data,l,sc);
131                         p[sw++]=l;
132                         for (; sw<MD5_LBLOCK; sw++)
133                                 {
134                                 c2l(data,l);
135                                 p[sw]=l;
136                                 }
137                         len-=(MD5_CBLOCK-c->num);
138
139                         md5_block(c,p,64);
140                         c->num=0;
141                         /* drop through and do the rest */
142                         }
143                 else
144                         {
145                         int ew,ec;
146
147                         c->num+=(int)len;
148                         if ((sc+len) < 4) /* ugly, add char's to a word */
149                                 {
150                                 l= p[sw];
151                                 p_c2l_p(data,l,sc,len);
152                                 p[sw]=l;
153                                 }
154                         else
155                                 {
156                                 ew=(c->num>>2);
157                                 ec=(c->num&0x03);
158                                 l= p[sw];
159                                 p_c2l(data,l,sc);
160                                 p[sw++]=l;
161                                 for (; sw < ew; sw++)
162                                         { c2l(data,l); p[sw]=l; }
163                                 if (ec)
164                                         {
165                                         c2l_p(data,l,ec);
166                                         p[sw]=l;
167                                         }
168                                 }
169                         return;
170                         }
171                 }
172         /* we now can process the input data in blocks of MD5_CBLOCK
173          * chars and save the leftovers to c->data. */
174 #ifdef L_ENDIAN
175         if ((((unsigned long)data)%sizeof(ULONG)) == 0)
176                 {
177                 sw=(int)len/MD5_CBLOCK;
178                 if (sw > 0)
179                         {
180                         sw*=MD5_CBLOCK;
181                         md5_block(c,(ULONG *)data,sw);
182                         data+=sw;
183                         len-=sw;
184                         }
185                 }
186 #endif
187         p=c->data;
188         while (len >= MD5_CBLOCK)
189                 {
190 #if defined(L_ENDIAN) || defined(B_ENDIAN)
191                 if (p != (unsigned long *)data)
192                         memcpy(p,data,MD5_CBLOCK);
193                 data+=MD5_CBLOCK;
194 #ifdef B_ENDIAN
195                 for (sw=(MD5_LBLOCK/4); sw; sw--)
196                         {
197                         Endian_Reverse32(p[0]);
198                         Endian_Reverse32(p[1]);
199                         Endian_Reverse32(p[2]);
200                         Endian_Reverse32(p[3]);
201                         p+=4;
202                         }
203 #endif
204 #else
205                 for (sw=(MD5_LBLOCK/4); sw; sw--)
206                         {
207                         c2l(data,l); *(p++)=l;
208                         c2l(data,l); *(p++)=l;
209                         c2l(data,l); *(p++)=l;
210                         c2l(data,l); *(p++)=l; 
211                         } 
212 #endif
213                 p=c->data;
214                 md5_block(c,p,64);
215                 len-=MD5_CBLOCK;
216                 }
217         sc=(int)len;
218         c->num=sc;
219         if (sc)
220                 {
221                 sw=sc>>2;       /* words to copy */
222 #ifdef L_ENDIAN
223                 p[sw]=0;
224                 memcpy(p,data,sc);
225 #else
226                 sc&=0x03;
227                 for ( ; sw; sw--)
228                         { c2l(data,l); *(p++)=l; }
229                 c2l_p(data,l,sc);
230                 *p=l;
231 #endif
232                 }
233         }
234
235 void MD5_Transform(c,b)
236 MD5_CTX *c;
237 unsigned char *b;
238         {
239         ULONG p[16];
240 #if !defined(L_ENDIAN)
241         ULONG *q;
242         int i;
243 #endif
244
245 #if defined(B_ENDIAN) || defined(L_ENDIAN)
246         memcpy(p,b,64);
247 #ifdef B_ENDIAN
248         q=p;
249         for (i=(MD5_LBLOCK/4); i; i--)
250                 {
251                 Endian_Reverse32(q[0]);
252                 Endian_Reverse32(q[1]);
253                 Endian_Reverse32(q[2]);
254                 Endian_Reverse32(q[3]);
255                 q+=4;
256                 }
257 #endif
258 #else
259         q=p;
260         for (i=(MD5_LBLOCK/4); i; i--)
261                 {
262                 ULONG l;
263                 c2l(b,l); *(q++)=l;
264                 c2l(b,l); *(q++)=l;
265                 c2l(b,l); *(q++)=l;
266                 c2l(b,l); *(q++)=l; 
267                 } 
268 #endif
269         md5_block(c,p,64);
270         }
271
272 #ifndef MD5_ASM
273
274 static void md5_block(c, X, num)
275 MD5_CTX *c;
276 register ULONG *X;
277 int num;
278         {
279         register ULONG A,B,C,D;
280
281         A=c->A;
282         B=c->B;
283         C=c->C;
284         D=c->D;
285         for (;;)
286                 {
287         /* Round 0 */
288         R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
289         R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
290         R0(C,D,A,B,X[ 2],17,0x242070dbL);
291         R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
292         R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
293         R0(D,A,B,C,X[ 5],12,0x4787c62aL);
294         R0(C,D,A,B,X[ 6],17,0xa8304613L);
295         R0(B,C,D,A,X[ 7],22,0xfd469501L);
296         R0(A,B,C,D,X[ 8], 7,0x698098d8L);
297         R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
298         R0(C,D,A,B,X[10],17,0xffff5bb1L);
299         R0(B,C,D,A,X[11],22,0x895cd7beL);
300         R0(A,B,C,D,X[12], 7,0x6b901122L);
301         R0(D,A,B,C,X[13],12,0xfd987193L);
302         R0(C,D,A,B,X[14],17,0xa679438eL);
303         R0(B,C,D,A,X[15],22,0x49b40821L);
304         /* Round 1 */
305         R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
306         R1(D,A,B,C,X[ 6], 9,0xc040b340L);
307         R1(C,D,A,B,X[11],14,0x265e5a51L);
308         R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
309         R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
310         R1(D,A,B,C,X[10], 9,0x02441453L);
311         R1(C,D,A,B,X[15],14,0xd8a1e681L);
312         R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
313         R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
314         R1(D,A,B,C,X[14], 9,0xc33707d6L);
315         R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
316         R1(B,C,D,A,X[ 8],20,0x455a14edL);
317         R1(A,B,C,D,X[13], 5,0xa9e3e905L);
318         R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
319         R1(C,D,A,B,X[ 7],14,0x676f02d9L);
320         R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
321         /* Round 2 */
322         R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
323         R2(D,A,B,C,X[ 8],11,0x8771f681L);
324         R2(C,D,A,B,X[11],16,0x6d9d6122L);
325         R2(B,C,D,A,X[14],23,0xfde5380cL);
326         R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
327         R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
328         R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
329         R2(B,C,D,A,X[10],23,0xbebfbc70L);
330         R2(A,B,C,D,X[13], 4,0x289b7ec6L);
331         R2(D,A,B,C,X[ 0],11,0xeaa127faL);
332         R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
333         R2(B,C,D,A,X[ 6],23,0x04881d05L);
334         R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
335         R2(D,A,B,C,X[12],11,0xe6db99e5L);
336         R2(C,D,A,B,X[15],16,0x1fa27cf8L);
337         R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
338         /* Round 3 */
339         R3(A,B,C,D,X[ 0], 6,0xf4292244L);
340         R3(D,A,B,C,X[ 7],10,0x432aff97L);
341         R3(C,D,A,B,X[14],15,0xab9423a7L);
342         R3(B,C,D,A,X[ 5],21,0xfc93a039L);
343         R3(A,B,C,D,X[12], 6,0x655b59c3L);
344         R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
345         R3(C,D,A,B,X[10],15,0xffeff47dL);
346         R3(B,C,D,A,X[ 1],21,0x85845dd1L);
347         R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
348         R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
349         R3(C,D,A,B,X[ 6],15,0xa3014314L);
350         R3(B,C,D,A,X[13],21,0x4e0811a1L);
351         R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
352         R3(D,A,B,C,X[11],10,0xbd3af235L);
353         R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
354         R3(B,C,D,A,X[ 9],21,0xeb86d391L);
355
356         A+=c->A&0xffffffffL;
357         B+=c->B&0xffffffffL;
358         c->A=A;
359         c->B=B;
360         C+=c->C&0xffffffffL;
361         D+=c->D&0xffffffffL;
362         c->C=C;
363         c->D=D;
364         X+=16;
365         num-=64;
366         if (num <= 0) break;
367                 }
368         }
369 #endif
370
371 void MD5_Final(md, c)
372 unsigned char *md;
373 MD5_CTX *c;
374         {
375         register int i,j;
376         register ULONG l;
377         register ULONG *p;
378         static unsigned char end[4]={0x80,0x00,0x00,0x00};
379         unsigned char *cp=end;
380
381         /* c->num should definitly have room for at least one more byte. */
382         p=c->data;
383         j=c->num;
384         i=j>>2;
385
386         /* purify often complains about the following line as an
387          * Uninitialized Memory Read.  While this can be true, the
388          * following p_c2l macro will reset l when that case is true.
389          * This is because j&0x03 contains the number of 'valid' bytes
390          * already in p[i].  If and only if j&0x03 == 0, the UMR will
391          * occur but this is also the only time p_c2l will do
392          * l= *(cp++) instead of l|= *(cp++)
393          * Many thanks to Alex Tang <altitude@cic.net> for pickup this
394          * 'potential bug' */
395 #ifdef PURIFY
396         if ((j&0x03) == 0) p[i]=0;
397 #endif
398         l=p[i];
399         p_c2l(cp,l,j&0x03);
400         p[i]=l;
401         i++;
402         /* i is the next 'undefined word' */
403         if (c->num >= MD5_LAST_BLOCK)
404                 {
405                 for (; i<MD5_LBLOCK; i++)
406                         p[i]=0;
407                 md5_block(c,p,64);
408                 i=0;
409                 }
410         for (; i<(MD5_LBLOCK-2); i++)
411                 p[i]=0;
412         p[MD5_LBLOCK-2]=c->Nl;
413         p[MD5_LBLOCK-1]=c->Nh;
414         md5_block(c,p,64);
415         cp=md;
416         l=c->A; l2c(l,cp);
417         l=c->B; l2c(l,cp);
418         l=c->C; l2c(l,cp);
419         l=c->D; l2c(l,cp);
420
421         /* clear stuff, md5_block may be leaving some stuff on the stack
422          * but I'm not worried :-) */
423         c->num=0;
424 /*      memset((char *)&c,0,sizeof(c));*/
425         }
426
427 #ifdef undef
428 int printit(l)
429 unsigned long *l;
430         {
431         int i,ii;
432
433         for (i=0; i<2; i++)
434                 {
435                 for (ii=0; ii<8; ii++)
436                         {
437                         fprintf(stderr,"%08lx ",l[i*8+ii]);
438                         }
439                 fprintf(stderr,"\n");
440                 }
441         }
442 #endif