patch genisoimage multi extent
[platform/upstream/cdrkit.git] / genisoimage / md5.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /*
14  * This code implements the MD5 message-digest algorithm.
15  * The algorithm is due to Ron Rivest.  This code was
16  * written by Colin Plumb in 1993, no copyright is claimed.
17  * This code is in the public domain; do with it what you wish.
18  *
19  * Equivalent code is available from RSA Data Security, Inc.
20  * This code has been tested against that, and is equivalent,
21  * except that you don't need to include two pages of legalese
22  * with every copy.
23  *
24  * To compute the message digest of a chunk of bytes, declare an
25  * MD5Context structure, pass it to MD5Init, call MD5Update as
26  * needed on buffers full of bytes, and then call MD5Final, which
27  * will fill a supplied 16-byte array with the digest.
28  */
29
30 /* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
31    not require an integer type which is exactly 32 bits.  This work
32    draws on the changes for the same purpose by Tatu Ylonen
33    <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
34    that code, there is no copyright issue.  I hereby disclaim
35    copyright in any changes I have made; this code remains in the
36    public domain.  */
37
38 /* Note regarding cvs_* namespace: this avoids potential conflicts
39    with libraries such as some versions of Kerberos.  No particular
40    need to worry about whether the system supplies an MD5 library, as
41    this file is only about 3k of object code.  */
42
43 /* Steve McIntyre, 2004/05/31: borrowed this code from the CVS
44    library. s/cvs_/mk_/ across the source */
45
46 #ifdef HAVE_CONFIG_H
47 #include "config.h"
48 #endif
49
50 #include <string.h>     /* for memcpy() and memset() */
51 #include <stdio.h>
52 #include <errno.h>
53 #include <stdlib.h>
54
55 #include "md5.h"
56
57 /* Little-endian byte-swapping routines.  Note that these do not
58    depend on the size of datatypes such as mk_uint32, nor do they require
59    us to detect the endianness of the machine we are running on.  It
60    is possible they should be macros for speed, but I would be
61    surprised if they were a performance bottleneck for MD5.  */
62
63 static mk_uint32
64 getu32 (const unsigned char *addr)
65 {
66         return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
67                 | addr[1]) << 8 | addr[0];
68 }
69
70 static void
71 putu32 (mk_uint32 data, unsigned char *addr)
72 {
73         addr[0] = (unsigned char)data;
74         addr[1] = (unsigned char)(data >> 8);
75         addr[2] = (unsigned char)(data >> 16);
76         addr[3] = (unsigned char)(data >> 24);
77 }
78
79 /*
80  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
81  * initialization constants.
82  */
83 void
84 mk_MD5Init (struct mk_MD5Context *ctx)
85 {
86         ctx->buf[0] = 0x67452301;
87         ctx->buf[1] = 0xefcdab89;
88         ctx->buf[2] = 0x98badcfe;
89         ctx->buf[3] = 0x10325476;
90
91         ctx->bits[0] = 0;
92         ctx->bits[1] = 0;
93 }
94
95 /*
96  * Update context to reflect the concatenation of another buffer full
97  * of bytes.
98  */
99 void
100 mk_MD5Update (struct mk_MD5Context *ctx, unsigned char const *buf, unsigned len)
101 {
102         mk_uint32 t;
103
104         /* Update bitcount */
105
106         t = ctx->bits[0];
107         if ((ctx->bits[0] = (t + ((mk_uint32)len << 3)) & 0xffffffff) < t)
108                 ctx->bits[1]++; /* Carry from low to high */
109         ctx->bits[1] += len >> 29;
110
111         t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */
112
113         /* Handle any leading odd-sized chunks */
114
115         if ( t ) {
116                 unsigned char *p = ctx->in + t;
117
118                 t = 64-t;
119                 if (len < t) {
120                         memcpy(p, buf, len);
121                         return;
122                 }
123                 memcpy(p, buf, t);
124                 mk_MD5Transform (ctx->buf, ctx->in);
125                 buf += t;
126                 len -= t;
127         }
128
129         /* Process data in 64-byte chunks */
130
131         while (len >= 64) {
132                 memcpy(ctx->in, buf, 64);
133                 mk_MD5Transform (ctx->buf, ctx->in);
134                 buf += 64;
135                 len -= 64;
136         }
137
138         /* Handle any remaining bytes of data. */
139
140         memcpy(ctx->in, buf, len);
141 }
142
143 /*
144  * Final wrapup - pad to 64-byte boundary with the bit pattern 
145  * 1 0* (64-bit count of bits processed, MSB-first)
146  */
147 void
148 mk_MD5Final (unsigned char digest[16], struct mk_MD5Context *ctx)
149 {
150         unsigned count;
151         unsigned char *p;
152
153         /* Compute number of bytes mod 64 */
154         count = (ctx->bits[0] >> 3) & 0x3F;
155
156         /* Set the first char of padding to 0x80.  This is safe since there is
157            always at least one byte free */
158         p = ctx->in + count;
159         *p++ = 0x80;
160
161         /* Bytes of padding needed to make 64 bytes */
162         count = 64 - 1 - count;
163
164         /* Pad out to 56 mod 64 */
165         if (count < 8) {
166                 /* Two lots of padding:  Pad the first block to 64 bytes */
167                 memset(p, 0, count);
168                 mk_MD5Transform (ctx->buf, ctx->in);
169
170                 /* Now fill the next block with 56 bytes */
171                 memset(ctx->in, 0, 56);
172         } else {
173                 /* Pad block to 56 bytes */
174                 memset(p, 0, count-8);
175         }
176
177         /* Append length in bits and transform */
178         putu32(ctx->bits[0], ctx->in + 56);
179         putu32(ctx->bits[1], ctx->in + 60);
180
181         mk_MD5Transform (ctx->buf, ctx->in);
182         putu32(ctx->buf[0], digest);
183         putu32(ctx->buf[1], digest + 4);
184         putu32(ctx->buf[2], digest + 8);
185         putu32(ctx->buf[3], digest + 12);
186         memset(ctx, 0, sizeof(ctx));    /* In case it's sensitive */
187 }
188
189 /* The four core functions - F1 is optimized somewhat */
190
191 /* #define F1(x, y, z) (x & y | ~x & z) */
192 #define F1(x, y, z) (z ^ (x & (y ^ z)))
193 #define F2(x, y, z) F1(z, x, y)
194 #define F3(x, y, z) (x ^ y ^ z)
195 #define F4(x, y, z) (y ^ (x | ~z))
196
197 /* This is the central step in the MD5 algorithm. */
198 #define MD5STEP(f, w, x, y, z, data, s) \
199         ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
200
201 /*
202  * The core of the MD5 algorithm, this alters an existing MD5 hash to
203  * reflect the addition of 16 longwords of new data.  MD5Update blocks
204  * the data and converts bytes into longwords for this routine.
205  */
206 void
207 mk_MD5Transform (mk_uint32 buf[4], const unsigned char inraw[64])
208 {
209         register mk_uint32 a, b, c, d;
210         mk_uint32 in[16];
211         int i;
212
213         for (i = 0; i < 16; ++i)
214                 in[i] = getu32 (inraw + 4 * i);
215
216         a = buf[0];
217         b = buf[1];
218         c = buf[2];
219         d = buf[3];
220
221         MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
222         MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
223         MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
224         MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
225         MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
226         MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
227         MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
228         MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
229         MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
230         MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
231         MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
232         MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
233         MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
234         MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
235         MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
236         MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
237
238         MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
239         MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
240         MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
241         MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
242         MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
243         MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
244         MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
245         MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
246         MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
247         MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
248         MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
249         MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
250         MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
251         MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
252         MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
253         MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
254
255         MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
256         MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
257         MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
258         MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
259         MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
260         MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
261         MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
262         MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
263         MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
264         MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
265         MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
266         MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
267         MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
268         MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
269         MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
270         MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
271
272         MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
273         MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
274         MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
275         MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
276         MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
277         MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
278         MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
279         MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
280         MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
281         MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
282         MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
283         MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
284         MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
285         MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
286         MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
287         MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
288
289         buf[0] += a;
290         buf[1] += b;
291         buf[2] += c;
292         buf[3] += d;
293 }
294
295 /* Read in a hex-dumped MD5 sum and parse it */
296 int mk_MD5Parse(unsigned char in[33], unsigned char out[16])
297 {
298     int i = 0;
299
300     for (i = 0; i < 16; i++)
301     {
302         if (in[2*i] >= '0' && in[2*i] <= '9')
303             in[2*i] -= '0';
304         else if (in[2*i] >= 'A' && in[2*i] <= 'F')
305             in[2*i] += 10 - 'A';
306         else if (in[2*i] >= 'a' && in[2*i] <= 'f')
307             in[2*i] += 10 - 'a';
308         else
309             return 1;
310         if (in[1+(2*i)] >= '0' && in[1+(2*i)] <= '9')
311             in[1+(2*i)] -= '0';
312         else if (in[1+(2*i)] >= 'A' && in[1+(2*i)] <= 'F')
313             in[1+(2*i)] += 10 - 'A';
314         else if (in[1+(2*i)] >= 'a' && in[1+(2*i)] <= 'f')
315             in[1+(2*i)] += 10 - 'a';
316         else
317             return 1;
318         out[i] = in[2*i] << 4 | in[1+(2*i)];
319     }
320     return 0;
321 }
322
323 /* Calculate the MD5sum of the specified file */
324 int calculate_md5sum(char *filename, unsigned long long size, unsigned char out[16])
325 {
326         char            buffer[32768];
327     int i = 0;
328     FILE *infile = NULL;
329     unsigned long long remain = 0;
330     int         use;
331     struct mk_MD5Context file_context;
332
333     /* Start MD5 work for the file */
334     mk_MD5Init(&file_context);
335
336     infile = fopen(filename, "rb");
337     if (!infile)
338     {
339 #ifndef HAVE_STRERROR
340                 fprintf(stderr, "cannot open '%s': (%d)\n",
341                                 filename, errno);
342 #else
343                 fprintf(stderr, "cannot open '%s': %s\n",
344                                 filename, strerror(errno));
345 #endif
346                 exit(1);
347         }
348
349     remain = size;
350     while (remain > 0)
351     {
352         use = (remain > sizeof(buffer) ? sizeof(buffer) : remain);
353         if (fread(buffer, 1, use, infile) == 0)
354         {
355                 fprintf(stderr, "cannot read from '%s'\n", filename);
356                 exit(1);
357         }
358         /* Update the checksum */
359         mk_MD5Update(&file_context, (unsigned char *)buffer, use);
360         remain -= use;
361     }
362     fclose(infile);
363     mk_MD5Final(&out[0], &file_context);
364
365     return 0;
366 }
367
368
369 #ifdef TEST
370 /* Simple test program.  Can use it to manually run the tests from
371    RFC1321 for example.  */
372 #include <stdio.h>
373
374 int
375 main (int argc, char *argv[])
376 {
377         struct mk_MD5Context context;
378         unsigned char checksum[16];
379         int i;
380         int j;
381
382         if (argc < 2)
383         {
384                 fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
385                 exit (1);
386         }
387         for (j = 1; j < argc; ++j)
388         {
389                 printf ("MD5 (\"%s\") = ", argv[j]);
390                 mk_MD5Init (&context);
391                 mk_MD5Update (&context, argv[j], strlen (argv[j]));
392                 mk_MD5Final (checksum, &context);
393                 for (i = 0; i < 16; i++)
394                 {
395                         printf ("%02x", (unsigned int) checksum[i]);
396                 }
397                 printf ("\n");
398         }
399         return 0;
400 }
401 #endif /* TEST */