comparison src/md5.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
2 */
3
4 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
5 rights reserved.
6
7 License to copy and use this software is granted provided that it
8 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
9 Algorithm" in all material mentioning or referencing this software
10 or this function.
11
12 License is also granted to make and use derivative works provided
13 that such works are identified as "derived from the RSA Data
14 Security, Inc. MD5 Message-Digest Algorithm" in all material
15 mentioning or referencing the derived work.
16
17 RSA Data Security, Inc. makes no representations concerning either
18 the merchantability of this software or the suitability of this
19 software for any particular purpose. It is provided "as is"
20 without express or implied warranty of any kind.
21
22 These notices must be retained in any copies of any part of this
23 documentation and/or software.
24 */
25
26 /* Synched up with: Not in FSF. */
27 /* This file has been Mule-ized. See comment at Fmd5(), though. */
28
29 #include <config.h>
30 #include "lisp.h"
31
32 #include "buffer.h"
33 #include "insdel.h"
34
35 typedef unsigned char *POINTER;/* POINTER defines a generic pointer type */
36 typedef unsigned short int UINT2;/* UINT2 defines a two byte word */
37 typedef unsigned long int UINT4;/* UINT4 defines a four byte word */
38
39 #define PROTO_LIST(list) list
40 #define MD_CTX MD5_CTX
41 #define MDInit MD5Init
42 #define MDUpdate MD5Update
43 #define MDFinal MD5Final
44
45 /* MD5 context. */
46 typedef struct {
47 UINT4 state[4]; /* state (ABCD) */
48 UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
49 unsigned char buffer[64]; /* input buffer */
50 } MD5_CTX;
51
52 void MD5Init PROTO_LIST ((MD5_CTX *));
53 void MD5Update PROTO_LIST
54 ((MD5_CTX *, CONST unsigned char *, unsigned int));
55 void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
56
57 /* Constants for MD5Transform routine.
58 */
59 #define S11 7
60 #define S12 12
61 #define S13 17
62 #define S14 22
63 #define S21 5
64 #define S22 9
65 #define S23 14
66 #define S24 20
67 #define S31 4
68 #define S32 11
69 #define S33 16
70 #define S34 23
71 #define S41 6
72 #define S42 10
73 #define S43 15
74 #define S44 21
75
76 static void MD5Transform PROTO_LIST ((UINT4 [4], CONST unsigned char [64]));
77 static void Encode PROTO_LIST
78 ((unsigned char *, UINT4 *, unsigned int));
79 static void Decode PROTO_LIST
80 ((UINT4 *, CONST unsigned char *, unsigned int));
81 static void MD5_memcpy PROTO_LIST ((POINTER, CONST POINTER, unsigned int));
82 static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
83
84 static unsigned char PADDING[64] = {
85 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
88 };
89
90 /* F, G, H and I are basic MD5 functions.
91 */
92 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
93 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
94 #define H(x, y, z) ((x) ^ (y) ^ (z))
95 #define I(x, y, z) ((y) ^ ((x) | (~z)))
96
97 /* ROTATE_LEFT rotates x left n bits.
98 */
99 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
100
101 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
102 Rotation is separate from addition to prevent recomputation.
103 */
104 #define FF(a, b, c, d, x, s, ac) { \
105 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
106 (a) = ROTATE_LEFT ((a), (s)); \
107 (a) += (b); \
108 }
109 #define GG(a, b, c, d, x, s, ac) { \
110 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
111 (a) = ROTATE_LEFT ((a), (s)); \
112 (a) += (b); \
113 }
114 #define HH(a, b, c, d, x, s, ac) { \
115 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
116 (a) = ROTATE_LEFT ((a), (s)); \
117 (a) += (b); \
118 }
119 #define II(a, b, c, d, x, s, ac) { \
120 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
121 (a) = ROTATE_LEFT ((a), (s)); \
122 (a) += (b); \
123 }
124
125 /* MD5 initialization. Begins an MD5 operation, writing a new context.
126 */
127 void
128 MD5Init (MD5_CTX *context)
129 {
130 context->count[0] = context->count[1] = 0;
131
132 /* Load magic initialization constants. */
133 context->state[0] = 0x67452301;
134 context->state[1] = 0xefcdab89;
135 context->state[2] = 0x98badcfe;
136 context->state[3] = 0x10325476;
137 }
138
139 /* MD5 block update operation. Continues an MD5 message-digest
140 operation, processing another message block, and updating the
141 context.
142 */
143 void
144 MD5Update (MD5_CTX *context, CONST unsigned char *input, unsigned int inputLen)
145 {
146 unsigned int i, indecks, partLen;
147
148 /* Compute number of bytes mod 64 */
149 indecks = (unsigned int)((context->count[0] >> 3) & 0x3F);
150
151 /* Update number of bits */
152 if ((context->count[0] += ((UINT4)inputLen << 3))
153 < ((UINT4)inputLen << 3))
154 context->count[1]++;
155 context->count[1] += ((UINT4)inputLen >> 29);
156
157 partLen = 64 - indecks;
158
159 /* Transform as many times as possible. */
160 if (inputLen >= partLen)
161 {
162 MD5_memcpy ((POINTER)&context->buffer[indecks], (CONST POINTER)input,
163 partLen);
164 MD5Transform (context->state, context->buffer);
165
166 for (i = partLen; i + 63 < inputLen; i += 64)
167 MD5Transform (context->state, &input[i]);
168
169 indecks = 0;
170 }
171 else
172 i = 0;
173
174 /* Buffer remaining input */
175 MD5_memcpy ((POINTER)&context->buffer[indecks], (CONST POINTER)&input[i],
176 inputLen-i);
177 }
178
179 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
180 the message digest and zeroizing the context.
181 */
182 void
183 MD5Final (unsigned char digest[16], MD5_CTX *context)
184 {
185 unsigned char bits[8];
186 unsigned int indecks, padLen;
187
188 /* Save number of bits */
189 Encode (bits, context->count, 8);
190
191 /* Pad out to 56 mod 64.
192 */
193 indecks = (unsigned int)((context->count[0] >> 3) & 0x3f);
194 padLen = (indecks < 56) ? (56 - indecks) : (120 - indecks);
195 MD5Update (context, PADDING, padLen);
196
197 /* Append length (before padding) */
198 MD5Update (context, bits, 8);
199 /* Store state in digest */
200 Encode (digest, context->state, 16);
201
202 /* Zeroize sensitive information.
203 */
204 MD5_memset ((POINTER)context, 0, sizeof (*context));
205 }
206
207 /* MD5 basic transformation. Transforms state based on block.
208 */
209 static void
210 MD5Transform (UINT4 state[4], CONST unsigned char block[64])
211 {
212 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
213
214 Decode (x, block, 64);
215
216 /* Round 1 */
217 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
218 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
219 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
220 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
221 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
222 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
223 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
224 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
225 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
226 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
227 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
228 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
229 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
230 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
231 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
232 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
233
234 /* Round 2 */
235 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
236 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
237 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
238 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
239 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
240 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
241 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
242 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
243 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
244 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
245 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
246 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
247 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
248 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
249 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
250 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
251
252 /* Round 3 */
253 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
254 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
255 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
256 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
257 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
258 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
259 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
260 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
261 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
262 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
263 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
264 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
265 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
266 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
267 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
268 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
269
270 /* Round 4 */
271 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
272 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
273 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
274 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
275 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
276 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
277 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
278 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
279 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
280 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
281 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
282 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
283 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
284 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
285 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
286 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
287
288 state[0] += a;
289 state[1] += b;
290 state[2] += c;
291 state[3] += d;
292
293 /* Zeroize sensitive information.
294 */
295 MD5_memset ((POINTER)x, 0, sizeof (x));
296 }
297
298 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
299 a multiple of 4.
300 */
301 static void
302 Encode (unsigned char *output, UINT4 *input, unsigned int len)
303 {
304 unsigned int i, j;
305
306 for (i = 0, j = 0; j < len; i++, j += 4)
307 {
308 output[j] = (unsigned char)(input[i] & 0xff);
309 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
310 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
311 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
312 }
313 }
314
315 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
316 a multiple of 4.
317 */
318 static void
319 Decode (UINT4 *output, CONST unsigned char *input, unsigned int len)
320 {
321 unsigned int i, j;
322
323 for (i = 0, j = 0; j < len; i++, j += 4)
324 output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
325 (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
326 }
327
328 static void
329 MD5_memcpy (POINTER output, CONST POINTER input, unsigned int len)
330 {
331 memcpy (output, input, len);
332 }
333
334 static void
335 MD5_memset (POINTER output, int value, unsigned int len)
336 {
337 memset (output, value, len);
338 }
339
340 /* unused */
341 #if 0
342 static void
343 LispMDString (char *string)
344 {
345 MD_CTX context;
346 unsigned char digest[16];
347 unsigned int len = strlen(string);
348
349 MDInit (&context);
350 MDUpdate (&context, string, len);
351 MDFinal (digest, &context);
352 }
353 #endif
354
355
356 /* XEmacs interface code. */
357 Lisp_Object Qmd5;
358
359 /* #### There could be potential problems here with Mule. I don't
360 know enough about the uses of MD5 to be able to tell for sure
361 whether this is a problem. The basic potential problem is that
362 the hash value will be computed based on the internal representation
363 of the buffer; this would likely cause problems if the string
364 contains extended characters, because the extended characters
365 will get sent over the wire in an external form that is different
366 from their internal representation, and thus their MD5 hash would
367 be different. */
368
369 DEFUN ("md5", Fmd5, Smd5, 1, 3, 0 /*
370 Return the MD5 (a secure message digest algorithm) of an object.
371 OBJECT is either a string or a buffer.
372 Optional arguments START and END denote buffer positions for computing the
373 hash of a portion of OBJECT.
374 */ )
375 (object, start, end)
376 Lisp_Object object, start, end;
377 {
378 MD_CTX context;
379 unsigned char digest[16];
380 unsigned char thehash[32];
381 int i;
382
383 MDInit (&context);
384
385 if (NILP (object))
386 {
387 MDUpdate (&context, (CONST unsigned char *) "", 0);
388 }
389 else if (BUFFERP (object))
390 {
391 struct buffer *b = decode_buffer (object, 1);
392 Bufpos begv, endv;
393 Lisp_Object string;
394
395 /* Figure out where we need to get info from */
396 get_buffer_range_char (b, start, end, &begv, &endv, GB_ALLOW_NIL);
397
398 /* Get the string data from the buffer */
399 string = make_string_from_buffer (b, begv, endv - begv);
400
401 /* Compute the digest */
402 MDUpdate (&context, (unsigned char *) string_data (XSTRING (string)),
403 string_length (XSTRING (string)));
404 }
405 else
406 {
407 Bytecount len, bstart, bend;
408 CHECK_STRING (object);
409 get_string_range_byte (object, start, end, &bstart, &bend,
410 GB_HISTORICAL_STRING_BEHAVIOR);
411 len = bend - bstart;
412 MDUpdate (&context, ((unsigned char *) string_data (XSTRING (object))
413 + bstart), len);
414 }
415
416 MDFinal (digest, &context);
417 for (i = 0; i < 16; i++)
418 sprintf ((char *) (thehash + (i * 2)), "%02x", digest[i]);
419
420 return (make_string (thehash, 32));
421 }
422
423 void
424 syms_of_md5 (void)
425 {
426 defsubr (&Smd5);
427 defsymbol (&Qmd5, "md5");
428 }
429
430 void
431 vars_of_md5 (void)
432 {
433 Fprovide (Qmd5);
434 }