Added icon for MadMatrix.
[AROS-Contrib.git] / sqlite3 / md5.c
blob1a20a4026aac8805de22dff1c0d150c5ae880b40
1 /*
2 * SQLite uses this code for testing only. It is not a part of the SQLite
3 * library. This file implements two new TCL commands "md5" and "md5file" that
4 * compute md5 checksums on arbitrary text and on complete files. These
5 * commands are used by the "testfixture" program to help verify the correct
6 * operation of the SQLite library.
8 * The original use of these TCL commands was to test the ROLLBACK feature of
9 * SQLite. First compute the MD5-checksum of the database. Then make some
10 * changes but rollback the changes rather than commit them. Compute a second
11 * MD5-checksum of the file and verify that the two checksums are the same.
12 * Such is the original use of this code. New uses may have been added since
13 * this comment was written.
14 * */
15 /**
16 * @file md5.c
18 * This code implements the MD5 message-digest algorithm. The algorithm is due
19 * to Ron Rivest. This code was written by Colin Plumb in 1993, no copyright is
20 * claimed. This code is in the public domain; do with it what you wish.
22 * Equivalent code is available from RSA Data Security, Inc. This code has been
23 * tested against that, and is equivalent, except that you don't need to
24 * include two pages of legalese with every copy.
26 * To compute the message digest of a chunk of bytes, declare an MD5Context
27 * structure, pass it to MD5Init, call MD5Update as needed on buffers full of
28 * bytes, and then call MD5Final, which will fill a supplied 16-byte array with
29 * the digest.
30 * */
31 #include <tcl.h>
32 #include <string.h>
33 #include "sqlite3.h"
36 * If compiled on a machine that doesn't have a 32-bit integer, you just set
37 * "uint32" to the appropriate datatype for an unsigned 32-bit integer. For
38 * example:
40 * cc -Duint32='unsigned long' md5.c
42 * */
43 #ifndef uint32
44 # define uint32 unsigned int
45 #endif
47 struct Context {
48 uint32 buf[4];
49 uint32 bits[2];
50 unsigned char in[64];
52 typedef char MD5Context[88];
55 * Note: this code is harmless on little-endian machines.
56 * */
57 static void byteReverse (unsigned char *buf, unsigned longs)
59 uint32 t;
60 do {
61 t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
62 ((unsigned)buf[1]<<8 | buf[0]);
63 *(uint32 *)buf = t;
64 buf += 4;
65 } while (--longs);
67 /* The four core functions - F1 is optimized somewhat */
69 /* #define F1(x, y, z) (x & y | ~x & z) */
70 #define F1(x, y, z) (z ^ (x & (y ^ z)))
71 #define F2(x, y, z) F1(z, x, y)
72 #define F3(x, y, z) (x ^ y ^ z)
73 #define F4(x, y, z) (y ^ (x | ~z))
75 /* This is the central step in the MD5 algorithm. */
76 #define MD5STEP(f, w, x, y, z, data, s) \
77 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
80 * The core of the MD5 algorithm, this alters an existing MD5 hash to
81 * reflect the addition of 16 longwords of new data. MD5Update blocks
82 * the data and converts bytes into longwords for this routine.
84 static void MD5Transform(uint32 buf[4], const uint32 in[16])
86 register uint32 a, b, c, d;
88 a = buf[0];
89 b = buf[1];
90 c = buf[2];
91 d = buf[3];
93 MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
94 MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
95 MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
96 MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
97 MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
98 MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
99 MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
100 MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
101 MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
102 MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
103 MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
104 MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
105 MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
106 MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
107 MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
108 MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
110 MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
111 MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
112 MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
113 MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
114 MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
115 MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
116 MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
117 MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
118 MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
119 MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
120 MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
121 MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
122 MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
123 MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
124 MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
125 MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
127 MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
128 MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
129 MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
130 MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
131 MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
132 MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
133 MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
134 MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
135 MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
136 MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
137 MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
138 MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
139 MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
140 MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
141 MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
142 MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
144 MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
145 MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
146 MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
147 MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
148 MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
149 MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
150 MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
151 MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
152 MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
153 MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
154 MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
155 MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
156 MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
157 MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
158 MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
159 MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
161 buf[0] += a;
162 buf[1] += b;
163 buf[2] += c;
164 buf[3] += d;
169 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
170 * initialization constants.
171 * */
172 static void MD5Init(MD5Context *pCtx)
174 struct Context *ctx = (struct Context *)pCtx;
175 ctx->buf[0] = 0x67452301;
176 ctx->buf[1] = 0xefcdab89;
177 ctx->buf[2] = 0x98badcfe;
178 ctx->buf[3] = 0x10325476;
179 ctx->bits[0] = 0;
180 ctx->bits[1] = 0;
185 * Update context to reflect the concatenation of another buffer full of bytes.
186 * */
187 static
188 void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len)
190 struct Context *ctx = (struct Context *)pCtx;
191 uint32 t;
193 /* Update bitcount */
195 t = ctx->bits[0];
196 if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
197 ctx->bits[1]++; /* Carry from low to high */
198 ctx->bits[1] += len >> 29;
200 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
202 /* Handle any leading odd-sized chunks */
204 if( t )
206 unsigned char *p = (unsigned char *)ctx->in + t;
208 t = 64-t;
209 if (len < t)
211 memcpy(p, buf, len);
212 return;
214 memcpy(p, buf, t);
215 byteReverse(ctx->in, 16);
216 MD5Transform(ctx->buf, (uint32 *)ctx->in);
217 buf += t;
218 len -= t;
221 /* Process data in 64-byte chunks */
223 while (len >= 64)
225 memcpy(ctx->in, buf, 64);
226 byteReverse(ctx->in, 16);
227 MD5Transform(ctx->buf, (uint32 *)ctx->in);
228 buf += 64;
229 len -= 64;
232 /* Handle any remaining bytes of data. */
233 memcpy(ctx->in, buf, len);
238 * Final wrapup - pad to 64-byte boundary with the bit pattern 1 0* (64-bit
239 * count of bits processed, MSB-first)
240 * */
241 static void MD5Final(unsigned char digest[16], MD5Context *pCtx)
243 struct Context *ctx = (struct Context *)pCtx;
244 unsigned count;
245 unsigned char *p;
247 /* Compute number of bytes mod 64 */
248 count = (ctx->bits[0] >> 3) & 0x3F;
251 * Set the first char of padding to 0x80. This is safe since there is
252 * always at least one byte free.
253 * */
254 p = ctx->in + count;
255 *p++ = 0x80;
257 /* Bytes of padding needed to make 64 bytes */
258 count = 64 - 1 - count;
260 /* Pad out to 56 mod 64 */
261 if (count < 8)
263 /* Two lots of padding: Pad the first block to 64 bytes */
264 memset(p, 0, count);
265 byteReverse(ctx->in, 16);
266 MD5Transform(ctx->buf, (uint32 *)ctx->in);
268 /* Now fill the next block with 56 bytes */
269 memset(ctx->in, 0, 56);
270 } else {
271 /* Pad block to 56 bytes */
272 memset(p, 0, count-8);
274 byteReverse(ctx->in, 14);
276 /* Append length in bits and transform */
277 ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
278 ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
280 MD5Transform(ctx->buf, (uint32 *)ctx->in);
281 byteReverse((unsigned char *)ctx->buf, 4);
282 memcpy(digest, ctx->buf, 16);
283 memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
288 * Convert a digest into base-16. digest should be declared as "unsigned char
289 * digest[16]" in the calling function. The MD5 digest is stored in the first
290 * 16 bytes. zBuf should be "char zBuf[33]".
291 * */
292 static void DigestToBase16(unsigned char *digest, char *zBuf)
294 static char const zEncode[] = "0123456789abcdef";
295 int i, j;
297 for( j=i=0; i<16; i++ )
299 int a = digest[i];
300 zBuf[j++] = zEncode[(a>>4)&0xf];
301 zBuf[j++] = zEncode[a & 0xf];
303 zBuf[j] = 0;
308 * A TCL command for md5. The argument is the text to be hashed. The Result is
309 * the hash in base64.
310 * */
311 static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv)
313 MD5Context ctx;
314 unsigned char digest[16];
316 if( argc!=2 )
318 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
319 " TEXT\"", 0);
320 return TCL_ERROR;
322 MD5Init(&ctx);
323 MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1]));
324 MD5Final(digest, &ctx);
325 DigestToBase16(digest, interp->result);
326 return TCL_OK;
331 * A TCL command to take the md5 hash of a file. The argument is the name of
332 * the file.
333 * */
334 static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv)
336 FILE *in;
337 MD5Context ctx;
338 unsigned char digest[16];
339 char zBuf[10240];
341 if( argc!=2 )
343 Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
344 " FILENAME\"", 0);
345 return TCL_ERROR;
347 in = fopen(argv[1],"rb");
348 if( in==0 )
350 Tcl_AppendResult(interp,"unable to open file \"", argv[1],
351 "\" for reading", 0);
352 return TCL_ERROR;
354 MD5Init(&ctx);
355 for(;;)
357 int n;
358 n = fread(zBuf, 1, sizeof(zBuf), in);
359 if( n<=0 ) break;
360 MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
362 fclose(in);
363 MD5Final(digest, &ctx);
364 DigestToBase16(digest, interp->result);
365 return TCL_OK;
370 * Register the two TCL commands above with the TCL interpreter.
371 * */
372 int Md5_Init(Tcl_Interp *interp)
374 Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, 0, 0);
375 Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, 0, 0);
376 return TCL_OK;
381 * During testing, the special md5sum() aggregate function is available.
382 * inside SQLite. The following routines implement that function.
383 * */
384 static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv)
386 MD5Context *p;
387 int i;
388 if( argc<1 ) return;
389 p = sqlite3_aggregate_context(context, sizeof(*p));
390 if( p==0 ) return;
391 if( sqlite3_aggregate_count(context)==1 )
392 MD5Init(p);
393 for(i=0; i<argc; i++)
395 const char *zData = sqlite3_value_text(argv[i]);
396 if( zData )
397 MD5Update(p, zData, strlen(zData));
400 static void md5finalize(sqlite3_context *context)
402 MD5Context *p;
403 unsigned char digest[16];
404 char zBuf[33];
405 p = sqlite3_aggregate_context(context, sizeof(*p));
406 MD5Final(digest,p);
407 DigestToBase16(digest, zBuf);
408 sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
410 void Md5_Register(sqlite3 *db)
412 sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
413 md5step, md5finalize);