]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/md5.c
Fix #define when using --disable-smartalloc
[bacula/bacula] / bacula / src / lib / md5.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * This code implements the MD5 message-digest algorithm.
30  * The algorithm is due to Ron Rivest.  This code was
31  * written by Colin Plumb in 1993, no copyright is claimed.
32  * This code is in the public domain; do with it what you wish.
33  *
34  * Equivalent code is available from RSA Data Security, Inc.
35  * This code has been tested against that, and is equivalent,
36  * except that you don't need to include two pages of legalese
37  * with every copy.
38  *
39  * To compute the message digest of a chunk of bytes, declare an
40  * MD5Context structure, pass it to MD5Init, call MD5Update as
41  * needed on buffers full of bytes, and then call MD5Final, which
42  * will fill a supplied 16-byte array with the digest.
43  *
44  *   Version $Id$
45  */
46
47 /* Brutally hacked by John Walker back from ANSI C to K&R (no
48    prototypes) to maintain the tradition that Netfone will compile
49    with Sun's original "cc". */
50
51
52
53 #include "bacula.h"
54
55 /*
56  * Note: this code is harmless on little-endian machines. We'll swap the bytes
57  * on big-endian machines.
58  */
59 void byteReverse(unsigned char *buf, unsigned longs)
60 {
61     uint32_t t;
62     if (bigendian()) {
63         do {
64             t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
65                 ((unsigned) buf[1] << 8 | buf[0]);
66             *(uint32_t *) buf = t;
67             buf += 4;
68         } while (--longs);
69     }
70 }
71
72 /*
73  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
74  * initialization constants.
75  */
76 void MD5Init(struct MD5Context *ctx)
77 {
78     ctx->buf[0] = 0x67452301;
79     ctx->buf[1] = 0xefcdab89;
80     ctx->buf[2] = 0x98badcfe;
81     ctx->buf[3] = 0x10325476;
82
83     ctx->bits[0] = 0;
84     ctx->bits[1] = 0;
85 }
86
87 /*
88  * Update context to reflect the concatenation of another buffer full
89  * of bytes.
90  */
91 void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len)
92 {
93     uint32_t t;
94
95     /* Update bitcount */
96
97     t = ctx->bits[0];
98     if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
99         ctx->bits[1]++;         /* Carry from low to high */
100     ctx->bits[1] += len >> 29;
101
102     t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
103
104     /* Handle any leading odd-sized chunks */
105
106     if (t) {
107         unsigned char *p = (unsigned char *) ctx->in + t;
108
109         t = 64 - t;
110         if (len < t) {
111             memcpy(p, buf, len);
112             return;
113         }
114         memcpy(p, buf, t);
115         byteReverse(ctx->in, 16);
116         MD5Transform(ctx->buf, (uint32_t *) ctx->in);
117         buf += t;
118         len -= t;
119     }
120     /* Process data in 64-byte chunks */
121
122     while (len >= 64) {
123         memcpy(ctx->in, buf, 64);
124         byteReverse(ctx->in, 16);
125         MD5Transform(ctx->buf, (uint32_t *) ctx->in);
126         buf += 64;
127         len -= 64;
128     }
129
130     /* Handle any remaining bytes of data. */
131
132     memcpy(ctx->in, buf, len);
133 }
134
135 /*
136  * Final wrapup - pad to 64-byte boundary with the bit pattern 
137  * 1 0* (64-bit count of bits processed, MSB-first)
138  */
139 void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
140 {
141     unsigned count;
142     unsigned char *p;
143
144     /* Compute number of bytes mod 64 */
145     count = (ctx->bits[0] >> 3) & 0x3F;
146
147     /* Set the first char of padding to 0x80.  This is safe since there is
148        always at least one byte free */
149     p = ctx->in + count;
150     *p++ = 0x80;
151
152     /* Bytes of padding needed to make 64 bytes */
153     count = 64 - 1 - count;
154
155     /* Pad out to 56 mod 64 */
156     if (count < 8) {
157         /* Two lots of padding:  Pad the first block to 64 bytes */
158         memset(p, 0, count);
159         byteReverse(ctx->in, 16);
160         MD5Transform(ctx->buf, (uint32_t *) ctx->in);
161
162         /* Now fill the next block with 56 bytes */
163         memset(ctx->in, 0, 56);
164     } else {
165         /* Pad block to 56 bytes */
166         memset(p, 0, count - 8);
167     }
168     byteReverse(ctx->in, 14);
169
170     /* Append length in bits and transform */
171     ((uint32_t *) ctx->in)[14] = ctx->bits[0];
172     ((uint32_t *) ctx->in)[15] = ctx->bits[1];
173
174     MD5Transform(ctx->buf, (uint32_t *) ctx->in);
175     byteReverse((unsigned char *) ctx->buf, 4);
176     memcpy(digest, ctx->buf, 16);
177     memset(ctx, 0, sizeof(ctx));        /* In case it's sensitive */
178 }
179
180
181 /* The four core functions - F1 is optimized somewhat */
182
183 /* #define F1(x, y, z) (x & y | ~x & z) */
184 #define F1(x, y, z) (z ^ (x & (y ^ z)))
185 #define F2(x, y, z) F1(z, x, y)
186 #define F3(x, y, z) (x ^ y ^ z)
187 #define F4(x, y, z) (y ^ (x | ~z))
188
189 /* This is the central step in the MD5 algorithm. */
190 #define MD5STEP(f, w, x, y, z, data, s) \
191         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
192
193 /*
194  * The core of the MD5 algorithm, this alters an existing MD5 hash to
195  * reflect the addition of 16 longwords of new data.  MD5Update blocks
196  * the data and converts bytes into longwords for this routine.
197  */
198 void MD5Transform(uint32_t buf[4], uint32_t in[16])
199 {
200     register uint32_t a, b, c, d;
201
202     a = buf[0];
203     b = buf[1];
204     c = buf[2];
205     d = buf[3];
206
207     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
208     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
209     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
210     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
211     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
212     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
213     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
214     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
215     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
216     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
217     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
218     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
219     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
220     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
221     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
222     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
223
224     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
225     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
226     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
227     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
228     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
229     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
230     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
231     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
232     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
233     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
234     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
235     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
236     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
237     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
238     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
239     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
240
241     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
242     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
243     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
244     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
245     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
246     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
247     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
248     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
249     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
250     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
251     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
252     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
253     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
254     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
255     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
256     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
257
258     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
259     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
260     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
261     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
262     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
263     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
264     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
265     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
266     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
267     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
268     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
269     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
270     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
271     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
272     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
273     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
274
275     buf[0] += a;
276     buf[1] += b;
277     buf[2] += c;
278     buf[3] += d;
279 }
280
281 #ifdef MD5_SUM
282 #define OUTPUT_BASE64 1
283
284 static void usage()
285 {
286    fprintf(stderr,
287 "\n"
288 "Usage: md5sum [-d decode] <data-file>\n"
289 "       -d          decode the data file\n"
290 "       -?          print this message.\n"
291 "\n\n");
292
293    exit(1);
294 }
295
296 static bool decode = false;
297
298 /*
299  * Reads a single ASCII file and prints the HEX md5 sum.
300  */
301 #include <stdio.h>
302 int main(int argc, char *argv[]) 
303 {
304    FILE *fd;
305    MD5Context ctx;
306    char buf[5000];
307    char signature[20];
308    int ch;
309
310    while ((ch = getopt(argc, argv, "d?")) != -1) {
311       switch (ch) {
312       case 'd':
313          decode = true;                
314          break;
315       case '?':
316       default:
317          usage();
318       }
319    }
320
321    argc -= optind;
322    argv += optind;
323
324    if (argc < 1) {
325       printf("Must have filename\n");
326       exit(1);
327    }
328
329    fd = fopen(argv[0], "rb");
330    if (!fd) {
331       printf("Could not open %s: ERR=%s\n", argv[0], strerror(errno));
332       exit(1);
333    }
334    if (decode) {
335       goto decode_it;
336    }
337    MD5Init(&ctx);
338    while (fgets(buf, sizeof(buf), fd)) {
339       MD5Update(&ctx, (unsigned char *)buf, strlen(buf));
340    }
341    MD5Final((unsigned char *)signature, &ctx);
342    for (int i=0; i < 16; i++) {
343       printf("%02x", signature[i]& 0xFF); 
344    }
345 #ifdef OUTPUT_BASE64
346    char MD5buf[40];                 /* 24 should do */ 
347    memset(MD5buf, 0, 40);
348    bin_to_base64(MD5buf, sizeof(MD5buf), (char *)signature, 16, true); /* encode 16 bytes */
349    printf("  %s", MD5buf);
350 #endif
351    printf("  %s\n", argv[0]);
352    exit(0);
353
354 decode_it:
355    while (fgets(buf, sizeof(buf), fd)) {
356       char bin[40];
357       unsigned char *p = (unsigned char *)buf;
358       unsigned char ch;
359       int val;
360       for (int i=0; i < 16; i++) {
361          if (*p <= '9') {
362             val = *p - '0';
363          } else {
364             val = *p - 'a' + 10;
365          }
366          ch = val << 4;
367          p++;
368          if (*p <= '9') {
369             val = *p - '0';
370          } else {
371             val = *p - 'a' + 10;
372          }
373          signature[i] = ch + val;
374          p++;
375       }
376       signature[16] = 0;
377       printf("%s", buf);
378       bin_to_base64(bin, sizeof(bin), (char *)signature, 16, true);
379       printf("%s\n", bin);
380    }
381    fclose(fd);
382 }
383 #endif