source: trunk/src/3rdparty/sqlite/md5.c@ 205

Last change on this file since 205 was 205, checked in by rudi, 14 years ago

Added SQLite 2.8.17 sources. This allows to build at least one of the sql drivers / plugins.

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