libStatGen Software  1
CSG_MD5.h
1 //
2 // This is a C++ friendly, limited use MD5 checksum copied
3 // from the reference implementation at http://www.ietf.org/rfc/rfc1321.txt
4 //
5 // The sole purpose of this file is to eliminate dependence on the
6 // openssl MD5 code, which poses a maintenance problem for general
7 // users trying to build libstatgen.
8 //
9 // It is intended to be included solely by GenomeSequence.cpp, which
10 // needs it to compute the MD5 checksum of chromosomes it is building.
11 //
12 
13 /* MDDRIVER.C - test driver for MD2, MD4 and MD5
14  */
15 
16 /* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
17 rights reserved.
18 
19 RSA Data Security, Inc. makes no representations concerning either
20 the merchantability of this software or the suitability of this
21 software for any particular purpose. It is provided "as is"
22 without express or implied warranty of any kind.
23 
24 These notices must be retained in any copies of any part of this
25 documentation and/or software.
26  */
27 
28 #include <stdio.h>
29 #include <time.h>
30 #include <string.h>
31 
32 /* MD5.H - header file for MD5C.C
33  */
34 
35 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
36 rights reserved.
37 
38 License to copy and use this software is granted provided that it
39 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
40 Algorithm" in all material mentioning or referencing this software
41 or this function.
42 
43 License is also granted to make and use derivative works provided
44 that such works are identified as "derived from the RSA Data
45 Security, Inc. MD5 Message-Digest Algorithm" in all material
46 mentioning or referencing the derived work.
47 
48 RSA Data Security, Inc. makes no representations concerning either
49 the merchantability of this software or the suitability of this
50 software for any particular purpose. It is provided "as is"
51 without express or implied warranty of any kind.
52 
53 These notices must be retained in any copies of any part of this
54 documentation and/or software.
55  */
56 
57 #include <stdint.h>
58 
59 /* MD5 context. */
60 typedef struct {
61  uint32_t state[4]; /* state (ABCD) */
62  uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
63  unsigned char buffer[64]; /* input buffer */
64 } MD5_CTX;
65 
66 static void MD5Init(MD5_CTX *);
67 static void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
68 static void MD5Final(unsigned char [16], MD5_CTX *);
69 
70 
71 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
72  */
73 
74 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
75 rights reserved.
76 
77 License to copy and use this software is granted provided that it
78 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
79 Algorithm" in all material mentioning or referencing this software
80 or this function.
81 
82 License is also granted to make and use derivative works provided
83 that such works are identified as "derived from the RSA Data
84 Security, Inc. MD5 Message-Digest Algorithm" in all material
85 mentioning or referencing the derived work.
86 
87 RSA Data Security, Inc. makes no representations concerning either
88 the merchantability of this software or the suitability of this
89 software for any particular purpose. It is provided "as is"
90 without express or implied warranty of any kind.
91 
92 These notices must be retained in any copies of any part of this
93 documentation and/or software.
94  */
95 
96 /* Constants for MD5Transform routine.
97  */
98 
99 #define S11 7
100 #define S12 12
101 #define S13 17
102 #define S14 22
103 #define S21 5
104 #define S22 9
105 #define S23 14
106 #define S24 20
107 #define S31 4
108 #define S32 11
109 #define S33 16
110 #define S34 23
111 #define S41 6
112 #define S42 10
113 #define S43 15
114 #define S44 21
115 
116 typedef unsigned char *POINTER;
117 
118 static void MD5Transform(uint32_t [4], unsigned char [64]);
119 static void Encode(unsigned char *, uint32_t *, unsigned int);
120 static void Decode(uint32_t *, unsigned char *, unsigned int);
121 static void MD5_memcpy(POINTER, POINTER, unsigned int);
122 static void MD5_memset(POINTER, int, unsigned int);
123 
124 static unsigned char PADDING[64] = {
125  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
126  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
127  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
128 };
129 
130 /* F, G, H and I are basic MD5 functions.
131  */
132 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
133 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
134 #define H(x, y, z) ((x) ^ (y) ^ (z))
135 #define I(x, y, z) ((y) ^ ((x) | (~z)))
136 
137 /* ROTATE_LEFT rotates x left n bits.
138  */
139 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
140 
141 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
142 Rotation is separate from addition to prevent recomputation.
143  */
144 #define FF(a, b, c, d, x, s, ac) { \
145  (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
146  (a) = ROTATE_LEFT ((a), (s)); \
147  (a) += (b); \
148  }
149 #define GG(a, b, c, d, x, s, ac) { \
150  (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
151  (a) = ROTATE_LEFT ((a), (s)); \
152  (a) += (b); \
153  }
154 #define HH(a, b, c, d, x, s, ac) { \
155  (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
156  (a) = ROTATE_LEFT ((a), (s)); \
157  (a) += (b); \
158  }
159 #define II(a, b, c, d, x, s, ac) { \
160  (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
161  (a) = ROTATE_LEFT ((a), (s)); \
162  (a) += (b); \
163  }
164 
165 /* MD5 initialization. Begins an MD5 operation, writing a new context.
166  */
167 static void MD5Init ( MD5_CTX *context) /* context */
168 {
169  context->count[0] = context->count[1] = 0;
170  /* Load magic initialization constants.
171 */
172  context->state[0] = 0x67452301;
173  context->state[1] = 0xefcdab89;
174  context->state[2] = 0x98badcfe;
175  context->state[3] = 0x10325476;
176 }
177 
178 /* MD5 block update operation. Continues an MD5 message-digest
179  operation, processing another message block, and updating the
180  context.
181  */
182 static void MD5Update (
183 MD5_CTX *context, /* context */
184 unsigned char *input, /* input block */
185 unsigned int inputLen) /* length of input block */
186 {
187  unsigned int i, index, partLen;
188 
189  /* Compute number of bytes mod 64 */
190  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
191 
192  /* Update number of bits */
193  if ((context->count[0] += ((uint32_t)inputLen << 3))
194  < ((uint32_t)inputLen << 3))
195  context->count[1]++;
196  context->count[1] += ((uint32_t)inputLen >> 29);
197 
198  partLen = 64 - index;
199 
200  /* Transform as many times as possible.
201 */
202  if (inputLen >= partLen) {
203  MD5_memcpy
204  ((POINTER)&context->buffer[index], (POINTER)input, partLen);
205  MD5Transform (context->state, context->buffer);
206 
207  for (i = partLen; i + 63 < inputLen; i += 64)
208  MD5Transform (context->state, &input[i]);
209 
210  index = 0;
211  }
212  else
213  i = 0;
214 
215  /* Buffer remaining input */
216  MD5_memcpy
217  ((POINTER)&context->buffer[index], (POINTER)&input[i],
218  inputLen-i);
219 }
220 
221 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
222  the message digest and zeroizing the context.
223  */
224 static void MD5Final (
225 unsigned char digest[16], /* message digest */
226 MD5_CTX *context) /* context */
227 {
228  unsigned char bits[8];
229  unsigned int index, padLen;
230 
231  /* Save number of bits */
232  Encode (bits, context->count, 8);
233 
234  /* Pad out to 56 mod 64.
235 */
236  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
237  padLen = (index < 56) ? (56 - index) : (120 - index);
238  MD5Update (context, PADDING, padLen);
239 
240  /* Append length (before padding) */
241  MD5Update (context, bits, 8);
242 
243  /* Store state in digest */
244  Encode (digest, context->state, 16);
245 
246  /* Zeroize sensitive information.
247 */
248  MD5_memset ((POINTER)context, 0, sizeof (*context));
249 }
250 
251 /* MD5 basic transformation. Transforms state based on block.
252  */
253 static void MD5Transform (
254 uint32_t state[4],
255 unsigned char block[64])
256 {
257  uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
258 
259  Decode (x, block, 64);
260 
261  /* Round 1 */
262  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
263  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
264  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
265  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
266  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
267  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
268  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
269  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
270  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
271  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
272  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
273  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
274  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
275  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
276  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
277  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
278 
279  /* Round 2 */
280  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
281  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
282  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
283  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
284  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
285  GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
286  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
287  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
288  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
289  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
290  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
291  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
292  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
293  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
294  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
295  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
296 
297  /* Round 3 */
298  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
299  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
300  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
301  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
302  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
303  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
304  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
305  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
306  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
307  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
308  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
309  HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
310  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
311  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
312  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
313  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
314 
315  /* Round 4 */
316  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
317  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
318  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
319  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
320  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
321  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
322  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
323  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
324  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
325  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
326  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
327  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
328  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
329  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
330  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
331  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
332 
333  state[0] += a;
334  state[1] += b;
335  state[2] += c;
336  state[3] += d;
337 
338  /* Zeroize sensitive information.
339 */
340  MD5_memset ((POINTER)x, 0, sizeof (x));
341 }
342 
343 /* Encodes input (uint32_t) into output (unsigned char). Assumes len is
344  a multiple of 4.
345  */
346 static void Encode (
347 unsigned char *output,
348 uint32_t *input,
349 unsigned int len)
350 {
351  unsigned int i, j;
352 
353  for (i = 0, j = 0; j < len; i++, j += 4) {
354  output[j] = (unsigned char)(input[i] & 0xff);
355  output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
356  output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
357  output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
358  }
359 }
360 
361 /* Decodes input (unsigned char) into output (uint32_t). Assumes len is
362  a multiple of 4.
363  */
364 static void Decode (
365 uint32_t *output,
366 unsigned char *input,
367 unsigned int len)
368 {
369  unsigned int i, j;
370 
371  for (i = 0, j = 0; j < len; i++, j += 4)
372  output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
373  (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
374 }
375 
376 /* Note: Replace "for loop" with standard memcpy if possible.
377  */
378 
379 static void MD5_memcpy (
380 POINTER output,
381 POINTER input,
382 unsigned int len)
383 {
384  unsigned int i;
385 
386  for (i = 0; i < len; i++)
387  output[i] = input[i];
388 }
389 
390 /* Note: Replace "for loop" with standard memset if possible.
391  */
392 static void MD5_memset (
393 POINTER output,
394 int value,
395 unsigned int len)
396 {
397  unsigned int i;
398 
399  for (i = 0; i < len; i++)
400  ((char *)output)[i] = (char)value;
401 }
402 
403 
MD5_CTX
Definition: CSG_MD5.h:60