1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/SRC/test_md5.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,401 @@
1.4 +/*
1.5 +**
1.6 +** Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
1.7 +**
1.8 +** SQLite uses this code for testing only. It is not a part of
1.9 +** the SQLite library. This file implements two new TCL commands
1.10 +** "md5" and "md5file" that compute md5 checksums on arbitrary text
1.11 +** and on complete files. These commands are used by the "testfixture"
1.12 +** program to help verify the correct operation of the SQLite library.
1.13 +**
1.14 +** The original use of these TCL commands was to test the ROLLBACK
1.15 +** feature of SQLite. First compute the MD5-checksum of the database.
1.16 +** Then make some changes but rollback the changes rather than commit
1.17 +** them. Compute a second MD5-checksum of the file and verify that the
1.18 +** two checksums are the same. Such is the original use of this code.
1.19 +** New uses may have been added since this comment was written.
1.20 +**
1.21 +** $Id: test_md5.c,v 1.8 2008/05/16 04:51:55 danielk1977 Exp $
1.22 +*/
1.23 +/*
1.24 + * This code implements the MD5 message-digest algorithm.
1.25 + * The algorithm is due to Ron Rivest. This code was
1.26 + * written by Colin Plumb in 1993, no copyright is claimed.
1.27 + * This code is in the public domain; do with it what you wish.
1.28 + *
1.29 + * Equivalent code is available from RSA Data Security, Inc.
1.30 + * This code has been tested against that, and is equivalent,
1.31 + * except that you don't need to include two pages of legalese
1.32 + * with every copy.
1.33 + *
1.34 + * To compute the message digest of a chunk of bytes, declare an
1.35 + * MD5Context structure, pass it to MD5Init, call MD5Update as
1.36 + * needed on buffers full of bytes, and then call MD5Final, which
1.37 + * will fill a supplied 16-byte array with the digest.
1.38 + */
1.39 +#include "tcl.h"
1.40 +#include <string.h>
1.41 +#include "sqlite3.h"
1.42 +#include <sys/param.h>
1.43 +
1.44 +/* Symbian OS */
1.45 +extern char* GetFullFilePath(char* aPath, const char* aFileName);
1.46 +
1.47 +/*
1.48 + * If compiled on a machine that doesn't have a 32-bit integer,
1.49 + * you just set "uint32" to the appropriate datatype for an
1.50 + * unsigned 32-bit integer. For example:
1.51 + *
1.52 + * cc -Duint32='unsigned long' md5.c
1.53 + *
1.54 + */
1.55 +#ifndef uint32
1.56 +# define uint32 unsigned int
1.57 +#endif
1.58 +
1.59 +struct Context {
1.60 + int isInit;
1.61 + uint32 buf[4];
1.62 + uint32 bits[2];
1.63 + unsigned char in[64];
1.64 +};
1.65 +typedef struct Context MD5Context;
1.66 +
1.67 +/*
1.68 + * Note: this code is harmless on little-endian machines.
1.69 + */
1.70 +static void byteReverse (unsigned char *buf, unsigned longs){
1.71 + uint32 t;
1.72 + do {
1.73 + t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
1.74 + ((unsigned)buf[1]<<8 | buf[0]);
1.75 + *(uint32 *)buf = t;
1.76 + buf += 4;
1.77 + } while (--longs);
1.78 +}
1.79 +/* The four core functions - F1 is optimized somewhat */
1.80 +
1.81 +/* #define F1(x, y, z) (x & y | ~x & z) */
1.82 +#define F1(x, y, z) (z ^ (x & (y ^ z)))
1.83 +#define F2(x, y, z) F1(z, x, y)
1.84 +#define F3(x, y, z) (x ^ y ^ z)
1.85 +#define F4(x, y, z) (y ^ (x | ~z))
1.86 +
1.87 +/* This is the central step in the MD5 algorithm. */
1.88 +#define MD5STEP(f, w, x, y, z, data, s) \
1.89 + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
1.90 +
1.91 +/*
1.92 + * The core of the MD5 algorithm, this alters an existing MD5 hash to
1.93 + * reflect the addition of 16 longwords of new data. MD5Update blocks
1.94 + * the data and converts bytes into longwords for this routine.
1.95 + */
1.96 +static void MD5Transform(uint32 buf[4], const uint32 in[16]){
1.97 + register uint32 a, b, c, d;
1.98 +
1.99 + a = buf[0];
1.100 + b = buf[1];
1.101 + c = buf[2];
1.102 + d = buf[3];
1.103 +
1.104 + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
1.105 + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
1.106 + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
1.107 + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
1.108 + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
1.109 + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
1.110 + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
1.111 + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
1.112 + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
1.113 + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
1.114 + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
1.115 + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
1.116 + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
1.117 + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
1.118 + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
1.119 + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
1.120 +
1.121 + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
1.122 + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
1.123 + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
1.124 + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
1.125 + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
1.126 + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
1.127 + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
1.128 + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
1.129 + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
1.130 + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
1.131 + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
1.132 + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
1.133 + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
1.134 + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
1.135 + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
1.136 + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
1.137 +
1.138 + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
1.139 + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
1.140 + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
1.141 + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
1.142 + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
1.143 + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
1.144 + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
1.145 + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
1.146 + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
1.147 + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
1.148 + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
1.149 + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
1.150 + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
1.151 + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
1.152 + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
1.153 + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
1.154 +
1.155 + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
1.156 + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
1.157 + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
1.158 + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
1.159 + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
1.160 + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
1.161 + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
1.162 + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
1.163 + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
1.164 + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
1.165 + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
1.166 + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
1.167 + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
1.168 + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
1.169 + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
1.170 + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
1.171 +
1.172 + buf[0] += a;
1.173 + buf[1] += b;
1.174 + buf[2] += c;
1.175 + buf[3] += d;
1.176 +}
1.177 +
1.178 +/*
1.179 + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
1.180 + * initialization constants.
1.181 + */
1.182 +static void MD5Init(MD5Context *ctx){
1.183 + ctx->isInit = 1;
1.184 + ctx->buf[0] = 0x67452301;
1.185 + ctx->buf[1] = 0xefcdab89;
1.186 + ctx->buf[2] = 0x98badcfe;
1.187 + ctx->buf[3] = 0x10325476;
1.188 + ctx->bits[0] = 0;
1.189 + ctx->bits[1] = 0;
1.190 +}
1.191 +
1.192 +/*
1.193 + * Update context to reflect the concatenation of another buffer full
1.194 + * of bytes.
1.195 + */
1.196 +static
1.197 +void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){
1.198 + struct Context *ctx = (struct Context *)pCtx;
1.199 + uint32 t;
1.200 +
1.201 + /* Update bitcount */
1.202 +
1.203 + t = ctx->bits[0];
1.204 + if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
1.205 + ctx->bits[1]++; /* Carry from low to high */
1.206 + ctx->bits[1] += len >> 29;
1.207 +
1.208 + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
1.209 +
1.210 + /* Handle any leading odd-sized chunks */
1.211 +
1.212 + if ( t ) {
1.213 + unsigned char *p = (unsigned char *)ctx->in + t;
1.214 +
1.215 + t = 64-t;
1.216 + if (len < t) {
1.217 + memcpy(p, buf, len);
1.218 + return;
1.219 + }
1.220 + memcpy(p, buf, t);
1.221 + byteReverse(ctx->in, 16);
1.222 + MD5Transform(ctx->buf, (uint32 *)ctx->in);
1.223 + buf += t;
1.224 + len -= t;
1.225 + }
1.226 +
1.227 + /* Process data in 64-byte chunks */
1.228 +
1.229 + while (len >= 64) {
1.230 + memcpy(ctx->in, buf, 64);
1.231 + byteReverse(ctx->in, 16);
1.232 + MD5Transform(ctx->buf, (uint32 *)ctx->in);
1.233 + buf += 64;
1.234 + len -= 64;
1.235 + }
1.236 +
1.237 + /* Handle any remaining bytes of data. */
1.238 +
1.239 + memcpy(ctx->in, buf, len);
1.240 +}
1.241 +
1.242 +/*
1.243 + * Final wrapup - pad to 64-byte boundary with the bit pattern
1.244 + * 1 0* (64-bit count of bits processed, MSB-first)
1.245 + */
1.246 +static void MD5Final(unsigned char digest[16], MD5Context *pCtx){
1.247 + struct Context *ctx = (struct Context *)pCtx;
1.248 + unsigned count;
1.249 + unsigned char *p;
1.250 +
1.251 + /* Compute number of bytes mod 64 */
1.252 + count = (ctx->bits[0] >> 3) & 0x3F;
1.253 +
1.254 + /* Set the first char of padding to 0x80. This is safe since there is
1.255 + always at least one byte free */
1.256 + p = ctx->in + count;
1.257 + *p++ = 0x80;
1.258 +
1.259 + /* Bytes of padding needed to make 64 bytes */
1.260 + count = 64 - 1 - count;
1.261 +
1.262 + /* Pad out to 56 mod 64 */
1.263 + if (count < 8) {
1.264 + /* Two lots of padding: Pad the first block to 64 bytes */
1.265 + memset(p, 0, count);
1.266 + byteReverse(ctx->in, 16);
1.267 + MD5Transform(ctx->buf, (uint32 *)ctx->in);
1.268 +
1.269 + /* Now fill the next block with 56 bytes */
1.270 + memset(ctx->in, 0, 56);
1.271 + } else {
1.272 + /* Pad block to 56 bytes */
1.273 + memset(p, 0, count-8);
1.274 + }
1.275 + byteReverse(ctx->in, 14);
1.276 +
1.277 + /* Append length in bits and transform */
1.278 + ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
1.279 + ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
1.280 +
1.281 + MD5Transform(ctx->buf, (uint32 *)ctx->in);
1.282 + byteReverse((unsigned char *)ctx->buf, 4);
1.283 + memcpy(digest, ctx->buf, 16);
1.284 + memset(ctx, 0, sizeof(ctx)); /* In case it is sensitive */
1.285 +}
1.286 +
1.287 +/*
1.288 +** Convert a digest into base-16. digest should be declared as
1.289 +** "unsigned char digest[16]" in the calling function. The MD5
1.290 +** digest is stored in the first 16 bytes. zBuf should
1.291 +** be "char zBuf[33]".
1.292 +*/
1.293 +static void DigestToBase16(unsigned char *digest, char *zBuf){
1.294 + static char const zEncode[] = "0123456789abcdef";
1.295 + int i, j;
1.296 +
1.297 + for(j=i=0; i<16; i++){
1.298 + int a = digest[i];
1.299 + zBuf[j++] = zEncode[(a>>4)&0xf];
1.300 + zBuf[j++] = zEncode[a & 0xf];
1.301 + }
1.302 + zBuf[j] = 0;
1.303 +}
1.304 +
1.305 +/*
1.306 +** A TCL command for md5. The argument is the text to be hashed. The
1.307 +** Result is the hash in base64.
1.308 +*/
1.309 +static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){
1.310 + MD5Context ctx;
1.311 + unsigned char digest[16];
1.312 +
1.313 + if( argc!=2 ){
1.314 + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
1.315 + " TEXT\"", 0);
1.316 + return TCL_ERROR;
1.317 + }
1.318 + MD5Init(&ctx);
1.319 + MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1]));
1.320 + MD5Final(digest, &ctx);
1.321 + DigestToBase16(digest, interp->result);
1.322 + return TCL_OK;
1.323 +}
1.324 +
1.325 +/*
1.326 +** A TCL command to take the md5 hash of a file. The argument is the
1.327 +** name of the file.
1.328 +*/
1.329 +static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){
1.330 + FILE *in;
1.331 + MD5Context ctx;
1.332 + unsigned char digest[16];
1.333 + char zBuf[10240];
1.334 + char fnamebuf[MAXPATHLEN + 1];
1.335 +
1.336 + if( argc!=2 ){
1.337 + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
1.338 + " FILENAME\"", 0);
1.339 + return TCL_ERROR;
1.340 + }
1.341 + if(GetFullFilePath(fnamebuf, argv[1]) == 0)
1.342 + return TCL_ERROR;
1.343 + in = fopen(fnamebuf,"rb");
1.344 + if( in==0 ){
1.345 + Tcl_AppendResult(interp,"unable to open file \"", fnamebuf, "\" for reading", 0);
1.346 + return TCL_ERROR;
1.347 + }
1.348 + MD5Init(&ctx);
1.349 + for(;;){
1.350 + int n;
1.351 + n = fread(zBuf, 1, sizeof(zBuf), in);
1.352 + if( n<=0 ) break;
1.353 + MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
1.354 + }
1.355 + fclose(in);
1.356 + MD5Final(digest, &ctx);
1.357 + DigestToBase16(digest, interp->result);
1.358 + return TCL_OK;
1.359 +}
1.360 +
1.361 +/*
1.362 +** Register the two TCL commands above with the TCL interpreter.
1.363 +*/
1.364 +int Md5_Init(Tcl_Interp *interp){
1.365 + Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, 0, 0);
1.366 + Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, 0, 0);
1.367 + return TCL_OK;
1.368 +}
1.369 +
1.370 +/*
1.371 +** During testing, the special md5sum() aggregate function is available.
1.372 +** inside SQLite. The following routines implement that function.
1.373 +*/
1.374 +static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
1.375 + MD5Context *p;
1.376 + int i;
1.377 + if( argc<1 ) return;
1.378 + p = sqlite3_aggregate_context(context, sizeof(*p));
1.379 + if( p==0 ) return;
1.380 + if( !p->isInit ){
1.381 + MD5Init(p);
1.382 + }
1.383 + for(i=0; i<argc; i++){
1.384 + const char *zData = (char*)sqlite3_value_text(argv[i]);
1.385 + if( zData ){
1.386 + MD5Update(p, (unsigned char*)zData, strlen(zData));
1.387 + }
1.388 + }
1.389 +}
1.390 +static void md5finalize(sqlite3_context *context){
1.391 + MD5Context *p;
1.392 + unsigned char digest[16];
1.393 + char zBuf[33];
1.394 + p = sqlite3_aggregate_context(context, sizeof(*p));
1.395 + MD5Final(digest,p);
1.396 + DigestToBase16(digest, zBuf);
1.397 + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
1.398 +}
1.399 +int Md5_Register(sqlite3 *db){
1.400 + int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
1.401 + md5step, md5finalize);
1.402 + sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */
1.403 + return rc;
1.404 +}