modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/test_md5.c (about)

     1  /*
     2  ** 2017-10-13
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  *************************************************************************
    12  **
    13  ** This file contains code to implement an MD5 extension to TCL.
    14  */
    15  #include "sqlite3.h"
    16  #include <stdlib.h>
    17  #include <string.h>
    18  #include "sqlite3.h"
    19  #if defined(INCLUDE_SQLITE_TCL_H)
    20  # include "sqlite_tcl.h"
    21  #else
    22  # include "tcl.h"
    23  # ifndef SQLITE_TCLAPI
    24  #  define SQLITE_TCLAPI
    25  # endif
    26  #endif
    27  
    28  /*
    29   * This code implements the MD5 message-digest algorithm.
    30   * The algorithm is due to Ron Rivest.  This code was
    31   * written by Colin Plumb in 1993, no copyright is claimed.
    32   * This code is in the public domain; do with it what you wish.
    33   *
    34   * Equivalent code is available from RSA Data Security, Inc.
    35   * This code has been tested against that, and is equivalent,
    36   * except that you don't need to include two pages of legalese
    37   * with every copy.
    38   *
    39   * To compute the message digest of a chunk of bytes, declare an
    40   * MD5Context structure, pass it to MD5Init, call MD5Update as
    41   * needed on buffers full of bytes, and then call MD5Final, which
    42   * will fill a supplied 16-byte array with the digest.
    43   */
    44  
    45  /*
    46   * If compiled on a machine that doesn't have a 32-bit integer,
    47   * you just set "uint32" to the appropriate datatype for an
    48   * unsigned 32-bit integer.  For example:
    49   *
    50   *       cc -Duint32='unsigned long' md5.c
    51   *
    52   */
    53  #ifndef uint32
    54  #  define uint32 unsigned int
    55  #endif
    56  
    57  struct MD5Context {
    58    int isInit;
    59    uint32 buf[4];
    60    uint32 bits[2];
    61    unsigned char in[64];
    62  };
    63  typedef struct MD5Context MD5Context;
    64  
    65  /*
    66   * Note: this code is harmless on little-endian machines.
    67   */
    68  static void byteReverse (unsigned char *buf, unsigned longs){
    69          uint32 t;
    70          do {
    71                  t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
    72                              ((unsigned)buf[1]<<8 | buf[0]);
    73                  *(uint32 *)buf = t;
    74                  buf += 4;
    75          } while (--longs);
    76  }
    77  /* The four core functions - F1 is optimized somewhat */
    78  
    79  /* #define F1(x, y, z) (x & y | ~x & z) */
    80  #define F1(x, y, z) (z ^ (x & (y ^ z)))
    81  #define F2(x, y, z) F1(z, x, y)
    82  #define F3(x, y, z) (x ^ y ^ z)
    83  #define F4(x, y, z) (y ^ (x | ~z))
    84  
    85  /* This is the central step in the MD5 algorithm. */
    86  #define MD5STEP(f, w, x, y, z, data, s) \
    87          ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
    88  
    89  /*
    90   * The core of the MD5 algorithm, this alters an existing MD5 hash to
    91   * reflect the addition of 16 longwords of new data.  MD5Update blocks
    92   * the data and converts bytes into longwords for this routine.
    93   */
    94  static void MD5Transform(uint32 buf[4], const uint32 in[16]){
    95          register uint32 a, b, c, d;
    96  
    97          a = buf[0];
    98          b = buf[1];
    99          c = buf[2];
   100          d = buf[3];
   101  
   102          MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
   103          MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
   104          MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
   105          MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
   106          MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
   107          MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
   108          MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
   109          MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
   110          MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
   111          MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
   112          MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
   113          MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
   114          MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
   115          MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
   116          MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
   117          MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
   118  
   119          MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
   120          MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
   121          MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
   122          MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
   123          MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
   124          MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
   125          MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
   126          MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
   127          MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
   128          MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
   129          MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
   130          MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
   131          MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
   132          MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
   133          MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
   134          MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
   135  
   136          MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
   137          MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
   138          MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
   139          MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
   140          MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
   141          MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
   142          MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
   143          MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
   144          MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
   145          MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
   146          MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
   147          MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
   148          MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
   149          MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
   150          MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
   151          MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
   152  
   153          MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
   154          MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
   155          MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
   156          MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
   157          MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
   158          MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
   159          MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
   160          MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
   161          MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
   162          MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
   163          MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
   164          MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
   165          MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
   166          MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
   167          MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
   168          MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
   169  
   170          buf[0] += a;
   171          buf[1] += b;
   172          buf[2] += c;
   173          buf[3] += d;
   174  }
   175  
   176  /*
   177   * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
   178   * initialization constants.
   179   */
   180  static void MD5Init(MD5Context *ctx){
   181          ctx->isInit = 1;
   182          ctx->buf[0] = 0x67452301;
   183          ctx->buf[1] = 0xefcdab89;
   184          ctx->buf[2] = 0x98badcfe;
   185          ctx->buf[3] = 0x10325476;
   186          ctx->bits[0] = 0;
   187          ctx->bits[1] = 0;
   188  }
   189  
   190  /*
   191   * Update context to reflect the concatenation of another buffer full
   192   * of bytes.
   193   */
   194  static
   195  void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
   196          uint32 t;
   197  
   198          /* Update bitcount */
   199  
   200          t = ctx->bits[0];
   201          if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
   202                  ctx->bits[1]++; /* Carry from low to high */
   203          ctx->bits[1] += len >> 29;
   204  
   205          t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */
   206  
   207          /* Handle any leading odd-sized chunks */
   208  
   209          if ( t ) {
   210                  unsigned char *p = (unsigned char *)ctx->in + t;
   211  
   212                  t = 64-t;
   213                  if (len < t) {
   214                          memcpy(p, buf, len);
   215                          return;
   216                  }
   217                  memcpy(p, buf, t);
   218                  byteReverse(ctx->in, 16);
   219                  MD5Transform(ctx->buf, (uint32 *)ctx->in);
   220                  buf += t;
   221                  len -= t;
   222          }
   223  
   224          /* Process data in 64-byte chunks */
   225  
   226          while (len >= 64) {
   227                  memcpy(ctx->in, buf, 64);
   228                  byteReverse(ctx->in, 16);
   229                  MD5Transform(ctx->buf, (uint32 *)ctx->in);
   230                  buf += 64;
   231                  len -= 64;
   232          }
   233  
   234          /* Handle any remaining bytes of data. */
   235  
   236          memcpy(ctx->in, buf, len);
   237  }
   238  
   239  /*
   240   * Final wrapup - pad to 64-byte boundary with the bit pattern
   241   * 1 0* (64-bit count of bits processed, MSB-first)
   242   */
   243  static void MD5Final(unsigned char digest[16], MD5Context *ctx){
   244          unsigned count;
   245          unsigned char *p;
   246  
   247          /* Compute number of bytes mod 64 */
   248          count = (ctx->bits[0] >> 3) & 0x3F;
   249  
   250          /* Set the first char of padding to 0x80.  This is safe since there is
   251             always at least one byte free */
   252          p = ctx->in + count;
   253          *p++ = 0x80;
   254  
   255          /* Bytes of padding needed to make 64 bytes */
   256          count = 64 - 1 - count;
   257  
   258          /* Pad out to 56 mod 64 */
   259          if (count < 8) {
   260                  /* Two lots of padding:  Pad the first block to 64 bytes */
   261                  memset(p, 0, count);
   262                  byteReverse(ctx->in, 16);
   263                  MD5Transform(ctx->buf, (uint32 *)ctx->in);
   264  
   265                  /* Now fill the next block with 56 bytes */
   266                  memset(ctx->in, 0, 56);
   267          } else {
   268                  /* Pad block to 56 bytes */
   269                  memset(p, 0, count-8);
   270          }
   271          byteReverse(ctx->in, 14);
   272  
   273          /* Append length in bits and transform */
   274          memcpy(ctx->in + 14*4, ctx->bits, 8);
   275  
   276          MD5Transform(ctx->buf, (uint32 *)ctx->in);
   277          byteReverse((unsigned char *)ctx->buf, 4);
   278          memcpy(digest, ctx->buf, 16);
   279  }
   280  
   281  /*
   282  ** Convert a 128-bit MD5 digest into a 32-digit base-16 number.
   283  */
   284  static void MD5DigestToBase16(unsigned char *digest, char *zBuf){
   285    static char const zEncode[] = "0123456789abcdef";
   286    int i, j;
   287  
   288    for(j=i=0; i<16; i++){
   289      int a = digest[i];
   290      zBuf[j++] = zEncode[(a>>4)&0xf];
   291      zBuf[j++] = zEncode[a & 0xf];
   292    }
   293    zBuf[j] = 0;
   294  }
   295  
   296  
   297  /*
   298  ** Convert a 128-bit MD5 digest into sequency of eight 5-digit integers
   299  ** each representing 16 bits of the digest and separated from each
   300  ** other by a "-" character.
   301  */
   302  static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){
   303    int i, j;
   304    unsigned int x;
   305    for(i=j=0; i<16; i+=2){
   306      x = digest[i]*256 + digest[i+1];
   307      if( i>0 ) zDigest[j++] = '-';
   308      sqlite3_snprintf(50-j, &zDigest[j], "%05u", x);
   309      j += 5;
   310    }
   311    zDigest[j] = 0;
   312  }
   313  
   314  /*
   315  ** A TCL command for md5.  The argument is the text to be hashed.  The
   316  ** Result is the hash in base64.
   317  */
   318  static int SQLITE_TCLAPI md5_cmd(
   319    void*cd,
   320    Tcl_Interp *interp,
   321    int argc,
   322    const char **argv
   323  ){
   324    MD5Context ctx;
   325    unsigned char digest[16];
   326    char zBuf[50];
   327    void (*converter)(unsigned char*, char*);
   328  
   329    if( argc!=2 ){
   330      Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
   331          " TEXT\"", (char*)0);
   332      return TCL_ERROR;
   333    }
   334    MD5Init(&ctx);
   335    MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1]));
   336    MD5Final(digest, &ctx);
   337    converter = (void(*)(unsigned char*,char*))cd;
   338    converter(digest, zBuf);
   339    Tcl_AppendResult(interp, zBuf, (char*)0);
   340    return TCL_OK;
   341  }
   342  
   343  /*
   344  ** A TCL command to take the md5 hash of a file.  The argument is the
   345  ** name of the file.
   346  */
   347  static int SQLITE_TCLAPI md5file_cmd(
   348    void*cd,
   349    Tcl_Interp *interp,
   350    int argc,
   351    const char **argv
   352  ){
   353    FILE *in;
   354    int ofst;
   355    int amt;
   356    MD5Context ctx;
   357    void (*converter)(unsigned char*, char*);
   358    unsigned char digest[16];
   359    char zBuf[10240];
   360  
   361    if( argc!=2 && argc!=4 ){
   362      Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
   363          " FILENAME [OFFSET AMT]\"", (char*)0);
   364      return TCL_ERROR;
   365    }
   366    if( argc==4 ){
   367      ofst = atoi(argv[2]);
   368      amt = atoi(argv[3]);
   369    }else{
   370      ofst = 0;
   371      amt = 2147483647;
   372    }
   373    in = fopen(argv[1],"rb");
   374    if( in==0 ){
   375      Tcl_AppendResult(interp,"unable to open file \"", argv[1],
   376           "\" for reading", (char*)0);
   377      return TCL_ERROR;
   378    }
   379    fseek(in, ofst, SEEK_SET);
   380    MD5Init(&ctx);
   381    while( amt>0 ){
   382      int n;
   383      n = (int)fread(zBuf, 1, sizeof(zBuf)<=amt ? sizeof(zBuf) : amt, in);
   384      if( n<=0 ) break;
   385      MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
   386      amt -= n;
   387    }
   388    fclose(in);
   389    MD5Final(digest, &ctx);
   390    converter = (void(*)(unsigned char*,char*))cd;
   391    converter(digest, zBuf);
   392    Tcl_AppendResult(interp, zBuf, (char*)0);
   393    return TCL_OK;
   394  }
   395  
   396  /*
   397  ** Register the four new TCL commands for generating MD5 checksums
   398  ** with the TCL interpreter.
   399  */
   400  int Md5_Init(Tcl_Interp *interp){
   401    Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd,
   402                      MD5DigestToBase16, 0);
   403    Tcl_CreateCommand(interp, "md5-10x8", (Tcl_CmdProc*)md5_cmd,
   404                      MD5DigestToBase10x8, 0);
   405    Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd,
   406                      MD5DigestToBase16, 0);
   407    Tcl_CreateCommand(interp, "md5file-10x8", (Tcl_CmdProc*)md5file_cmd,
   408                      MD5DigestToBase10x8, 0);
   409    return TCL_OK;
   410  }
   411  
   412  /*
   413  ** During testing, the special md5sum() aggregate function is available.
   414  ** inside SQLite.  The following routines implement that function.
   415  */
   416  static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
   417    MD5Context *p;
   418    int i;
   419    if( argc<1 ) return;
   420    p = sqlite3_aggregate_context(context, sizeof(*p));
   421    if( p==0 ) return;
   422    if( !p->isInit ){
   423      MD5Init(p);
   424    }
   425    for(i=0; i<argc; i++){
   426      const char *zData = (char*)sqlite3_value_text(argv[i]);
   427      if( zData ){
   428        MD5Update(p, (unsigned char*)zData, (int)strlen(zData));
   429      }
   430    }
   431  }
   432  static void md5finalize(sqlite3_context *context){
   433    MD5Context *p;
   434    unsigned char digest[16];
   435    char zBuf[33];
   436    p = sqlite3_aggregate_context(context, sizeof(*p));
   437    MD5Final(digest,p);
   438    MD5DigestToBase16(digest, zBuf);
   439    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
   440  }
   441  int Md5_Register(
   442    sqlite3 *db,
   443    char **pzErrMsg,
   444    const sqlite3_api_routines *pThunk
   445  ){
   446    int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
   447                                   md5step, md5finalize);
   448    sqlite3_overload_function(db, "md5sum", -1);  /* To exercise this API */
   449    return rc;
   450  }