dtcm: Resolve CID 87408
[oweals/cde.git] / cde / programs / dtcm / dtcm / md5.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 static char sccsid[] = "$XConsortium: md5.c /main/2 1996/03/25 10:28:16 rswiston $";
24 /*
25  *   COMPONENT_NAME: desktop
26  *
27  *   FUNCTIONS: Decode
28  *              Encode
29  *              F
30  *              FF
31  *              G
32  *              GG
33  *              H
34  *              HH
35  *              I
36  *              II
37  *              MD5Final
38  *              MD5Init
39  *              MD5Transform
40  *              MD5Update
41  *              MD5_memcpy
42  *              MD5_memset
43  *              ROTATE_LEFT
44  *
45  *   ORIGINS: 119
46  *
47  */
48 /*
49  *+SNOTICE
50  *
51  *
52  *      $Revision: /main/2 $
53  *
54  *      RESTRICTED CONFIDENTIAL INFORMATION:
55  *      
56  *      The information in this document is subject to special
57  *      restrictions in a confidential disclosure agreement bertween
58  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
59  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
60  *      Sun's specific written approval.  This documment and all copies
61  *      and derivative works thereof must be returned or destroyed at
62  *      Sun's request.
63  *
64  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
65  *
66  *+ENOTICE
67  */
68
69 #ifndef I_HAVE_NO_IDENT
70 #endif
71
72 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
73  */
74
75 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
76    rights reserved.
77    
78    License to copy and use this software is granted provided that it
79    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
80    Algorithm" in all material mentioning or referencing this software
81    or this function.
82    
83    License is also granted to make and use derivative works provided
84    that such works are identified as "derived from the RSA Data
85    Security, Inc. MD5 Message-Digest Algorithm" in all material
86    mentioning or referencing the derived work.
87    
88    RSA Data Security, Inc. makes no representations concerning either
89    the merchantability of this software or the suitability of this
90    software for any particular purpose. It is provided "as is"
91    without express or implied warranty of any kind.
92    
93    These notices must be retained in any copies of any part of this
94    documentation and/or software.
95    */
96
97 #include <string.h>
98 #include "md5.h"
99
100 /* Constants for MD5Transform routine.
101  */
102
103 #define S11 7
104 #define S12 12
105 #define S13 17
106 #define S14 22
107 #define S21 5
108 #define S22 9
109 #define S23 14
110 #define S24 20
111 #define S31 4
112 #define S32 11
113 #define S33 16
114 #define S34 23
115 #define S41 6
116 #define S42 10
117 #define S43 15
118 #define S44 21
119
120 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
121 static void Encode PROTO_LIST
122 ((unsigned char *, UINT4 *, unsigned int));
123 static void Decode PROTO_LIST
124 ((UINT4 *, unsigned char *, unsigned int));
125 static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
126 static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
127
128 static unsigned char PADDING[64] = {
129     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
132 };
133
134 /* F, G, H and I are basic MD5 functions.
135  */
136 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
137 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
138 #define H(x, y, z) ((x) ^ (y) ^ (z))
139 #define I(x, y, z) ((y) ^ ((x) | (~z)))
140
141 /* ROTATE_LEFT rotates x left n bits.
142  */
143 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
144
145 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
146    Rotation is separate from addition to prevent recomputation.
147    */
148 #define FF(a, b, c, d, x, s, ac) { \
149 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
150 (a) = ROTATE_LEFT ((a), (s)); \
151 (a) += (b); \
152 }
153 #define GG(a, b, c, d, x, s, ac) { \
154 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
155 (a) = ROTATE_LEFT ((a), (s)); \
156 (a) += (b); \
157 }
158 #define HH(a, b, c, d, x, s, ac) { \
159 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
160 (a) = ROTATE_LEFT ((a), (s)); \
161 (a) += (b); \
162 }
163 #define II(a, b, c, d, x, s, ac) { \
164 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
165 (a) = ROTATE_LEFT ((a), (s)); \
166 (a) += (b); \
167 }
168
169 /* MD5 initialization. Begins an MD5 operation, writing a new context.
170  */
171 void MD5Init (context)
172 MD5_CTX *context;                                        /* context */
173 {
174     context->count[0] = context->count[1] = 0;
175     /* Load magic initialization constants.
176      */
177     context->state[0] = 0x67452301;
178     context->state[1] = 0xefcdab89;
179     context->state[2] = 0x98badcfe;
180     context->state[3] = 0x10325476;
181 }
182
183 /* MD5 block update operation. Continues an MD5 message-digest
184    operation, processing another message block, and updating the
185    context.
186    */
187 void MD5Update (context, input, inputLen)
188 MD5_CTX *context;                                        /* context */
189 unsigned char *input;                                /* input block */
190 unsigned int inputLen;                     /* length of input block */
191 {
192     unsigned int i, index, partLen;
193     
194     /* Compute number of bytes mod 64 */
195     index = (unsigned int)((context->count[0] >> 3) & 0x3F);
196     
197     /* Update number of bits */
198     if ((context->count[0] += ((UINT4)inputLen << 3))
199         < ((UINT4)inputLen << 3))
200         context->count[1]++;
201     context->count[1] += ((UINT4)inputLen >> 29);
202     
203     partLen = 64 - index;
204     
205     /* Transform as many times as possible.
206      */
207     if (inputLen >= partLen) {
208         MD5_memcpy
209             ((POINTER)&context->buffer[index], (POINTER)input, partLen);
210         MD5Transform (context->state, context->buffer);
211         
212         for (i = partLen; i + 63 < inputLen; i += 64)
213             MD5Transform (context->state, &input[i]);
214         
215         index = 0;
216     }
217     else
218         i = 0;
219     
220     /* Buffer remaining input */
221     MD5_memcpy
222         ((POINTER)&context->buffer[index], (POINTER)&input[i],
223          inputLen-i);
224 }
225
226 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
227    the message digest and zeroizing the context.
228    */
229 void MD5Final (digest, context)
230 unsigned char digest[16];                         /* message digest */
231 MD5_CTX *context;                                       /* context */
232 {
233     unsigned char bits[8];
234     unsigned int index, padLen;
235     
236     /* Save number of bits */
237     Encode (bits, context->count, 8);
238     
239     /* Pad out to 56 mod 64.
240      */
241     index = (unsigned int)((context->count[0] >> 3) & 0x3f);
242     padLen = (index < 56) ? (56 - index) : (120 - index);
243     MD5Update (context, PADDING, padLen);
244     
245     /* Append length (before padding) */
246     MD5Update (context, bits, 8);
247     
248     /* Store state in digest */
249     Encode (digest, context->state, 16);
250     
251     /* Zeroize sensitive information.
252      */
253     MD5_memset ((POINTER)context, 0, sizeof (*context));
254 }
255
256 /* MD5 basic transformation. Transforms state based on block.
257  */
258 static void MD5Transform (state, block)
259 UINT4 state[4];
260 unsigned char block[64];
261 {
262     UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
263     
264     Decode (x, block, 64);
265     
266     /* Round 1 */
267     FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
268     FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
269     FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
270     FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
271     FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
272     FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
273     FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
274     FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
275     FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
276     FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
277     FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
278     FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
279     FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
280     FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
281     FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
282     FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
283     
284     /* Round 2 */
285     GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
286     GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
287     GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
288     GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
289     GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
290     GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
291     GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
292     GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
293     GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
294     GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
295     GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
296     GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
297     GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
298     GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
299     GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
300     GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
301     
302     /* Round 3 */
303     HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
304     HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
305     HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
306     HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
307     HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
308     HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
309     HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
310     HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
311     HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
312     HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
313     HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
314     HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
315     HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
316     HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
317     HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
318     HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
319     
320     /* Round 4 */
321     II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
322     II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
323     II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
324     II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
325     II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
326     II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
327     II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
328     II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
329     II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
330     II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
331     II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
332     II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
333     II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
334     II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
335     II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
336     II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
337     
338     state[0] += a;
339     state[1] += b;
340     state[2] += c;
341     state[3] += d;
342     
343     /* Zeroize sensitive information.
344      */
345     MD5_memset ((POINTER)x, 0, sizeof (x));
346 }
347
348 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
349    a multiple of 4.
350    */
351 static void Encode (output, input, len)
352 unsigned char *output;
353 UINT4 *input;
354 unsigned int len;
355 {
356     unsigned int i, j;
357     
358     for (i = 0, j = 0; j < len; i++, j += 4) {
359         output[j] = (unsigned char)(input[i] & 0xff);
360         output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
361         output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
362         output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
363     }
364 }
365
366 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
367    a multiple of 4.
368    */
369 static void Decode (output, input, len)
370 UINT4 *output;
371 unsigned char *input;
372 unsigned int len;
373 {
374     unsigned int i, j;
375     
376     for (i = 0, j = 0; j < len; i++, j += 4)
377         output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
378             (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
379 }
380
381 /* Note: Replace "for loop" with standard memcpy if possible.
382  */
383
384 static void MD5_memcpy (output, input, len)
385 POINTER output;
386 POINTER input;
387 unsigned int len;
388 {
389     memcpy(output, input, len);
390 }
391
392 /* Note: Replace "for loop" with standard memset if possible.
393  */
394 static void MD5_memset (output, value, len)
395 POINTER output;
396 int value;
397 unsigned int len;
398 {
399     memset(output, value, len);
400 }