libStatGen Software 1
Loading...
Searching...
No Matches
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
17rights reserved.
18
19RSA Data Security, Inc. makes no representations concerning either
20the merchantability of this software or the suitability of this
21software for any particular purpose. It is provided "as is"
22without express or implied warranty of any kind.
23
24These notices must be retained in any copies of any part of this
25documentation 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
36rights reserved.
37
38License to copy and use this software is granted provided that it
39is identified as the "RSA Data Security, Inc. MD5 Message-Digest
40Algorithm" in all material mentioning or referencing this software
41or this function.
42
43License is also granted to make and use derivative works provided
44that such works are identified as "derived from the RSA Data
45Security, Inc. MD5 Message-Digest Algorithm" in all material
46mentioning or referencing the derived work.
47
48RSA Data Security, Inc. makes no representations concerning either
49the merchantability of this software or the suitability of this
50software for any particular purpose. It is provided "as is"
51without express or implied warranty of any kind.
52
53These notices must be retained in any copies of any part of this
54documentation and/or software.
55 */
56
57#include <stdint.h>
58
59/* MD5 context. */
60typedef 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
66static void MD5Init(MD5_CTX *);
67static void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
68static 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
75rights reserved.
76
77License to copy and use this software is granted provided that it
78is identified as the "RSA Data Security, Inc. MD5 Message-Digest
79Algorithm" in all material mentioning or referencing this software
80or this function.
81
82License is also granted to make and use derivative works provided
83that such works are identified as "derived from the RSA Data
84Security, Inc. MD5 Message-Digest Algorithm" in all material
85mentioning or referencing the derived work.
86
87RSA Data Security, Inc. makes no representations concerning either
88the merchantability of this software or the suitability of this
89software for any particular purpose. It is provided "as is"
90without express or implied warranty of any kind.
91
92These notices must be retained in any copies of any part of this
93documentation 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
116typedef unsigned char *POINTER;
117
118static void MD5Transform(uint32_t [4], unsigned char [64]);
119static void Encode(unsigned char *, uint32_t *, unsigned int);
120static void Decode(uint32_t *, unsigned char *, unsigned int);
121static void MD5_memcpy(POINTER, POINTER, unsigned int);
122static void MD5_memset(POINTER, int, unsigned int);
123
124static 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.
142Rotation 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 */
167static 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 */
182static void MD5Update (
183MD5_CTX *context, /* context */
184unsigned char *input, /* input block */
185unsigned 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 */
224static void MD5Final (
225unsigned char digest[16], /* message digest */
226MD5_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 */
253static void MD5Transform (
254uint32_t state[4],
255unsigned 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 */
346static void Encode (
347unsigned char *output,
348uint32_t *input,
349unsigned 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 */
364static void Decode (
365uint32_t *output,
366unsigned char *input,
367unsigned 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
379static void MD5_memcpy (
380POINTER output,
381POINTER input,
382unsigned 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 */
392static void MD5_memset (
393POINTER output,
394int value,
395unsigned int len)
396{
397 unsigned int i;
398
399 for (i = 0; i < len; i++)
400 ((char *)output)[i] = (char)value;
401}
402
403