1/* $Id: pc_md5.c 14574 2005-10-29 16:27:43Z bonefish $
2 *
3 * PDFlib MD5 message digest routines
4 *
5 */
6
7/* This is a slightly modified version of the RSA reference
8 * implementation for MD5, which originally contained
9 * the following copyright notice:
10 */
11
12/*  Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
13    rights reserved.
14
15    License to copy and use this software is granted provided that it
16    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
17    Algorithm" in all material mentioning or referencing this software
18    or this function.
19
20    License is also granted to make and use derivative works provided
21    that such works are identified as "derived from the RSA Data
22    Security, Inc. MD5 Message-Digest Algorithm" in all material
23    mentioning or referencing the derived work.
24
25    RSA Data Security, Inc. makes no representations concerning either
26    the merchantability of this software or the suitability of this
27    software for any particular purpose. It is provided "as is"
28    without express or implied warranty of any kind.
29
30    These notices must be retained in any copies of any part of this
31    documentation and/or software.
32*/
33
34#include <string.h>
35
36#include "pc_util.h"
37#include "pc_md5.h"
38
39/* Constants for MD5_Transform routine.
40 */
41#define S11 7
42#define S12 12
43#define S13 17
44#define S14 22
45#define S21 5
46#define S22 9
47#define S23 14
48#define S24 20
49#define S31 4
50#define S32 11
51#define S33 16
52#define S34 23
53#define S41 6
54#define S42 10
55#define S43 15
56#define S44 21
57
58static unsigned char PADDING[64] = {
59  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
62};
63
64/* F, G, H and I are basic MD5 functions.
65 */
66#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
67#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
68#define H(x, y, z) ((x) ^ (y) ^ (z))
69#define I(x, y, z) ((y) ^ ((x) | (~z)))
70
71/* ROTATE_LEFT rotates x left n bits.
72 */
73#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
74
75/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
76 * Rotation is separate from addition to prevent recomputation.
77 */
78#define FF(a, b, c, d, x, s, ac) { \
79	(a) += F ((b), (c), (d)) + (x) + (MD5_UINT4)(ac); \
80	(a) = ROTATE_LEFT ((a), (s)); \
81	(a) += (b); \
82}
83#define GG(a, b, c, d, x, s, ac) { \
84	(a) += G ((b), (c), (d)) + (x) + (MD5_UINT4)(ac); \
85	(a) = ROTATE_LEFT ((a), (s)); \
86	(a) += (b); \
87}
88#define HH(a, b, c, d, x, s, ac) { \
89	(a) += H ((b), (c), (d)) + (x) + (MD5_UINT4)(ac); \
90	(a) = ROTATE_LEFT ((a), (s)); \
91	(a) += (b); \
92}
93#define II(a, b, c, d, x, s, ac) { \
94	(a) += I ((b), (c), (d)) + (x) + (MD5_UINT4)(ac); \
95	(a) = ROTATE_LEFT ((a), (s)); \
96	(a) += (b); \
97}
98
99
100/* Encodes input (MD5_UINT4) into output (unsigned char). Assumes len is
101 * a multiple of 4.
102 */
103static void Encode(unsigned char *output, MD5_UINT4 *input, unsigned int len)
104{
105    unsigned int i, j;
106
107    for (i = 0, j = 0; j < len; i++, j += 4) {
108	output[j]   = (unsigned char) (input[i] & 0xff);
109	output[j+1] = (unsigned char) ((input[i] >> 8) & 0xff);
110	output[j+2] = (unsigned char) ((input[i] >> 16) & 0xff);
111	output[j+3] = (unsigned char) ((input[i] >> 24) & 0xff);
112    }
113}
114
115/* Decodes input (unsigned char) into output (MD5_UINT4). Assumes len is
116 * a multiple of 4.
117 */
118static void Decode(
119    MD5_UINT4 *output,
120    const unsigned char *input,
121    unsigned int len)
122{
123    unsigned int i, j;
124
125    for (i = 0, j = 0; j < len; i++, j += 4)
126	output[i] = ((MD5_UINT4) input[j]) |
127		    (((MD5_UINT4) input[j+1]) << 8) |
128		    (((MD5_UINT4) input[j+2]) << 16) |
129		    (((MD5_UINT4) input[j+3]) << 24);
130}
131
132/* MD5 basic transformation. Transforms state based on block.
133 */
134static void MD5_Transform(MD5_UINT4 state[4], const unsigned char block[64])
135{
136    MD5_UINT4 a = state[0];
137    MD5_UINT4 b = state[1];
138    MD5_UINT4 c = state[2];
139    MD5_UINT4 d = state[3];
140    MD5_UINT4 x[16];
141
142    Decode(x, block, 64);
143
144    /* Round 1 */
145    FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
146    FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
147    FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
148    FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
149    FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
150    FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
151    FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
152    FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
153    FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
154    FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
155    FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
156    FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
157    FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
158    FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
159    FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
160    FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
161
162    /* Round 2 */
163    GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
164    GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
165    GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
166    GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
167    GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
168    GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
169    GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
170    GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
171    GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
172    GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
173    GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
174    GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
175    GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
176    GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
177    GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
178    GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
179
180    /* Round 3 */
181    HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
182    HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
183    HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
184    HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
185    HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
186    HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
187    HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
188    HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
189    HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
190    HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
191    HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
192    HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
193    HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
194    HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
195    HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
196    HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
197
198    /* Round 4 */
199    II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
200    II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
201    II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
202    II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
203    II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
204    II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
205    II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
206    II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
207    II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
208    II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
209    II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
210    II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
211    II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
212    II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
213    II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
214    II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
215
216    state[0] += a;
217    state[1] += b;
218    state[2] += c;
219    state[3] += d;
220
221    /* Zeroize sensitive information.
222    */
223    memset (x, 0, sizeof (x));
224}
225
226/* MD5 initialization. Begins an MD5 operation, writing a new context.
227 */
228void MD5_Init(MD5_CTX *context)
229{
230    context->count[0] = context->count[1] = 0;
231
232    /* Load magic initialization constants.
233    */
234    context->state[0] = 0x67452301;
235    context->state[1] = 0xefcdab89;
236    context->state[2] = 0x98badcfe;
237    context->state[3] = 0x10325476;
238}
239
240/* MD5 block update operation. Continues an MD5 message-digest
241 * operation, processing another message block, and updating the
242 * context.
243 */
244void MD5_Update(
245    MD5_CTX *context,
246    const unsigned char *input,
247    unsigned int inputLen)
248{
249    unsigned int i, idx, partLen;
250
251    /* Compute number of bytes mod 64 */
252    idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
253
254    /* Update number of bits */
255    if ((context->count[0] += ((MD5_UINT4) inputLen << 3))
256	< ((MD5_UINT4) inputLen << 3))
257	context->count[1]++;
258
259    context->count[1] += ((MD5_UINT4) inputLen >> 29);
260
261    partLen = 64 - idx;
262
263    /* Transform as many times as possible.
264    */
265    if (inputLen >= partLen) {
266	memcpy(&context->buffer[idx], input, partLen);
267	MD5_Transform(context->state, context->buffer);
268
269	for (i = partLen; i + 63 < inputLen; i += 64)
270	    MD5_Transform (context->state, &input[i]);
271
272	idx = 0;
273    }
274    else
275	i = 0;
276
277    /* Buffer remaining input */
278    memcpy(&context->buffer[idx], &input[i], inputLen - i);
279}
280
281/* MD5 finalization. Ends an MD5 message-digest operation, writing the
282 * the message digest and zeroizing the context.
283 */
284void MD5_Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *context)
285{
286    unsigned char bits[8];
287    unsigned int idx, padLen;
288
289    /* Save number of bits */
290    Encode(bits, context->count, 8);
291
292    /* Pad out to 56 mod 64.
293    */
294    idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
295    padLen = (idx < 56) ? (56 - idx) : (120 - idx);
296    MD5_Update(context, PADDING, padLen);
297
298    /* Append length (before padding) */
299    MD5_Update(context, bits, 8);
300
301    /* Store state in digest */
302    Encode(digest, context->state, 16);
303
304    /* Zeroize sensitive information.
305    */
306    memset(context, 0, sizeof (*context));
307}
308