gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

pmd5.cxx (15310B)


      1 /*
      2  *
      3  *  C++ Portable Types Library (PTypes)
      4  *  Version 2.1.1  Released 27-Jun-2007
      5  *
      6  *  Copyright (C) 2001-2007 Hovik Melikyan
      7  *
      8  *  http://www.melikyan.com/ptypes/
      9  *
     10  */
     11 
     12 /*
     13  *   Derived from L. Peter Deutsch's independent implementation
     14  *   of MD5 (RFC1321). The original copyright notice follows.
     15  *   This file is a concatenation of the original md5.h and
     16  *   md5.c and contains PTypes' MD5 wrapper class at the bottom.
     17  */
     18 
     19 /*
     20   Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
     21 
     22   This software is provided 'as-is', without any express or implied
     23   warranty.  In no event will the authors be held liable for any damages
     24   arising from the use of this software.
     25 
     26   Permission is granted to anyone to use this software for any purpose,
     27   including commercial applications, and to alter it and redistribute it
     28   freely, subject to the following restrictions:
     29 
     30   1. The origin of this software must not be misrepresented; you must not
     31      claim that you wrote the original software. If you use this software
     32      in a product, an acknowledgment in the product documentation would be
     33      appreciated but is not required.
     34   2. Altered source versions must be plainly marked as such, and must not be
     35      misrepresented as being the original software.
     36   3. This notice may not be removed or altered from any source distribution.
     37 
     38   L. Peter Deutsch
     39   ghost@aladdin.com
     40 
     41  */
     42 
     43 /*
     44   Independent implementation of MD5 (RFC 1321).
     45 
     46   This code implements the MD5 Algorithm defined in RFC 1321, whose
     47   text is available at
     48 	http://www.ietf.org/rfc/rfc1321.txt
     49   The code is derived from the text of the RFC, including the test suite
     50   (section A.5) but excluding the rest of Appendix A.  It does not include
     51   any code or documentation that is identified in the RFC as being
     52   copyrighted.
     53 
     54   The original and principal author of md5.h is L. Peter Deutsch
     55   <ghost@aladdin.com>.  Other authors are noted in the change history
     56   that follows (in reverse chronological order):
     57 
     58   2002-04-13 lpd Removed support for non-ANSI compilers; removed
     59 	references to Ghostscript; clarified derivation from RFC 1321;
     60 	now handles byte order either statically or dynamically.
     61   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
     62   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
     63 	added conditionalization for C++ compilation from Martin
     64 	Purschke <purschke@bnl.gov>.
     65   1999-05-03 lpd Original version.
     66  */
     67 
     68 
     69 #include <string.h>
     70 
     71 #include "pstreams.h"
     72 
     73 
     74 namespace ptypes {
     75 
     76 
     77 //
     78 // --- md5.h ---------------------------------------------------------------
     79 //
     80 
     81 /*
     82  * This package supports both compile-time and run-time determination of CPU
     83  * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
     84  * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
     85  * defined as non-zero, the code will be compiled to run only on big-endian
     86  * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
     87  * run on either big- or little-endian CPUs, but will run slightly less
     88  * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
     89  */
     90 
     91 
     92 //
     93 // typedef unsigned char md5_byte_t; /* 8-bit byte */
     94 // typedef unsigned int md5_word_t; /* 32-bit word */
     95 // 
     96 // /* Define the state of the MD5 Algorithm. */
     97 // typedef struct md5_state_s {
     98 //     md5_word_t count[2];	/* message length in bits, lsw first */
     99 //     md5_word_t abcd[4];		/* digest buffer */
    100 //     md5_byte_t buf[64];		/* accumulate block */
    101 // } md5_state_t;
    102 // 
    103 
    104 /* Initialize the algorithm. */
    105 void md5_init(md5_state_t *pms);
    106 
    107 /* Append a string to the message. */
    108 void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
    109 
    110 /* Finish the message and return the digest. */
    111 void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
    112 
    113 
    114 //
    115 // --- md5.c ---------------------------------------------------------------
    116 //
    117 
    118 
    119 #undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
    120 #ifdef ARCH_IS_BIG_ENDIAN
    121 #  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
    122 #else
    123 #  define BYTE_ORDER 0
    124 #endif
    125 
    126 #define T_MASK ((md5_word_t)~0)
    127 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
    128 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
    129 #define T3    0x242070db
    130 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
    131 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
    132 #define T6    0x4787c62a
    133 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
    134 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
    135 #define T9    0x698098d8
    136 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
    137 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
    138 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
    139 #define T13    0x6b901122
    140 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
    141 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
    142 #define T16    0x49b40821
    143 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
    144 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
    145 #define T19    0x265e5a51
    146 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
    147 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
    148 #define T22    0x02441453
    149 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
    150 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
    151 #define T25    0x21e1cde6
    152 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
    153 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
    154 #define T28    0x455a14ed
    155 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
    156 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
    157 #define T31    0x676f02d9
    158 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
    159 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
    160 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
    161 #define T35    0x6d9d6122
    162 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
    163 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
    164 #define T38    0x4bdecfa9
    165 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
    166 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
    167 #define T41    0x289b7ec6
    168 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
    169 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
    170 #define T44    0x04881d05
    171 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
    172 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
    173 #define T47    0x1fa27cf8
    174 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
    175 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
    176 #define T50    0x432aff97
    177 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
    178 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
    179 #define T53    0x655b59c3
    180 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
    181 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
    182 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
    183 #define T57    0x6fa87e4f
    184 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
    185 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
    186 #define T60    0x4e0811a1
    187 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
    188 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
    189 #define T63    0x2ad7d2bb
    190 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
    191 
    192 
    193 static void
    194 md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
    195 {
    196     md5_word_t
    197 	a = pms->abcd[0], b = pms->abcd[1],
    198 	c = pms->abcd[2], d = pms->abcd[3];
    199     md5_word_t t;
    200 #if BYTE_ORDER > 0
    201     /* Define storage only for big-endian CPUs. */
    202     md5_word_t X[16];
    203 #else
    204     /* Define storage for little-endian or both types of CPUs. */
    205     md5_word_t xbuf[16];
    206     const md5_word_t *X;
    207 #endif
    208 
    209     {
    210 #if BYTE_ORDER == 0
    211 	/*
    212 	 * Determine dynamically whether this is a big-endian or
    213 	 * little-endian machine, since we can use a more efficient
    214 	 * algorithm on the latter.
    215 	 */
    216 	static const int w = 1;
    217 
    218 	if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
    219 #endif
    220 #if BYTE_ORDER <= 0		/* little-endian */
    221 	{
    222 	    /*
    223 	     * On little-endian machines, we can process properly aligned
    224 	     * data without copying it.
    225 	     */
    226 	    if (!((data - (const md5_byte_t *)0) & 3)) {
    227 		/* data are properly aligned */
    228 		X = (const md5_word_t *)data;
    229 	    } else {
    230 		/* not aligned */
    231 		memcpy(xbuf, data, 64);
    232 		X = xbuf;
    233 	    }
    234 	}
    235 #endif
    236 #if BYTE_ORDER == 0
    237 	else			/* dynamic big-endian */
    238 #endif
    239 #if BYTE_ORDER >= 0		/* big-endian */
    240 	{
    241 	    /*
    242 	     * On big-endian machines, we must arrange the bytes in the
    243 	     * right order.
    244 	     */
    245 	    const md5_byte_t *xp = data;
    246 	    int i;
    247 
    248 #  if BYTE_ORDER == 0
    249 	    X = xbuf;		/* (dynamic only) */
    250 #  else
    251 #    define xbuf X		/* (static only) */
    252 #  endif
    253 	    for (i = 0; i < 16; ++i, xp += 4)
    254 		xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
    255 	}
    256 #endif
    257     }
    258 
    259 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
    260 
    261     /* Round 1. */
    262     /* Let [abcd k s i] denote the operation
    263        a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
    264 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
    265 #define SET(a, b, c, d, k, s, Ti)\
    266   t = a + F(b,c,d) + X[k] + Ti;\
    267   a = ROTATE_LEFT(t, s) + b
    268     /* Do the following 16 operations. */
    269     SET(a, b, c, d,  0,  7,  T1);
    270     SET(d, a, b, c,  1, 12,  T2);
    271     SET(c, d, a, b,  2, 17,  T3);
    272     SET(b, c, d, a,  3, 22,  T4);
    273     SET(a, b, c, d,  4,  7,  T5);
    274     SET(d, a, b, c,  5, 12,  T6);
    275     SET(c, d, a, b,  6, 17,  T7);
    276     SET(b, c, d, a,  7, 22,  T8);
    277     SET(a, b, c, d,  8,  7,  T9);
    278     SET(d, a, b, c,  9, 12, T10);
    279     SET(c, d, a, b, 10, 17, T11);
    280     SET(b, c, d, a, 11, 22, T12);
    281     SET(a, b, c, d, 12,  7, T13);
    282     SET(d, a, b, c, 13, 12, T14);
    283     SET(c, d, a, b, 14, 17, T15);
    284     SET(b, c, d, a, 15, 22, T16);
    285 #undef SET
    286 
    287      /* Round 2. */
    288      /* Let [abcd k s i] denote the operation
    289           a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
    290 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
    291 #define SET(a, b, c, d, k, s, Ti)\
    292   t = a + G(b,c,d) + X[k] + Ti;\
    293   a = ROTATE_LEFT(t, s) + b
    294      /* Do the following 16 operations. */
    295     SET(a, b, c, d,  1,  5, T17);
    296     SET(d, a, b, c,  6,  9, T18);
    297     SET(c, d, a, b, 11, 14, T19);
    298     SET(b, c, d, a,  0, 20, T20);
    299     SET(a, b, c, d,  5,  5, T21);
    300     SET(d, a, b, c, 10,  9, T22);
    301     SET(c, d, a, b, 15, 14, T23);
    302     SET(b, c, d, a,  4, 20, T24);
    303     SET(a, b, c, d,  9,  5, T25);
    304     SET(d, a, b, c, 14,  9, T26);
    305     SET(c, d, a, b,  3, 14, T27);
    306     SET(b, c, d, a,  8, 20, T28);
    307     SET(a, b, c, d, 13,  5, T29);
    308     SET(d, a, b, c,  2,  9, T30);
    309     SET(c, d, a, b,  7, 14, T31);
    310     SET(b, c, d, a, 12, 20, T32);
    311 #undef SET
    312 
    313      /* Round 3. */
    314      /* Let [abcd k s t] denote the operation
    315           a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
    316 #define H(x, y, z) ((x) ^ (y) ^ (z))
    317 #define SET(a, b, c, d, k, s, Ti)\
    318   t = a + H(b,c,d) + X[k] + Ti;\
    319   a = ROTATE_LEFT(t, s) + b
    320      /* Do the following 16 operations. */
    321     SET(a, b, c, d,  5,  4, T33);
    322     SET(d, a, b, c,  8, 11, T34);
    323     SET(c, d, a, b, 11, 16, T35);
    324     SET(b, c, d, a, 14, 23, T36);
    325     SET(a, b, c, d,  1,  4, T37);
    326     SET(d, a, b, c,  4, 11, T38);
    327     SET(c, d, a, b,  7, 16, T39);
    328     SET(b, c, d, a, 10, 23, T40);
    329     SET(a, b, c, d, 13,  4, T41);
    330     SET(d, a, b, c,  0, 11, T42);
    331     SET(c, d, a, b,  3, 16, T43);
    332     SET(b, c, d, a,  6, 23, T44);
    333     SET(a, b, c, d,  9,  4, T45);
    334     SET(d, a, b, c, 12, 11, T46);
    335     SET(c, d, a, b, 15, 16, T47);
    336     SET(b, c, d, a,  2, 23, T48);
    337 #undef SET
    338 
    339      /* Round 4. */
    340      /* Let [abcd k s t] denote the operation
    341           a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
    342 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
    343 #define SET(a, b, c, d, k, s, Ti)\
    344   t = a + I(b,c,d) + X[k] + Ti;\
    345   a = ROTATE_LEFT(t, s) + b
    346      /* Do the following 16 operations. */
    347     SET(a, b, c, d,  0,  6, T49);
    348     SET(d, a, b, c,  7, 10, T50);
    349     SET(c, d, a, b, 14, 15, T51);
    350     SET(b, c, d, a,  5, 21, T52);
    351     SET(a, b, c, d, 12,  6, T53);
    352     SET(d, a, b, c,  3, 10, T54);
    353     SET(c, d, a, b, 10, 15, T55);
    354     SET(b, c, d, a,  1, 21, T56);
    355     SET(a, b, c, d,  8,  6, T57);
    356     SET(d, a, b, c, 15, 10, T58);
    357     SET(c, d, a, b,  6, 15, T59);
    358     SET(b, c, d, a, 13, 21, T60);
    359     SET(a, b, c, d,  4,  6, T61);
    360     SET(d, a, b, c, 11, 10, T62);
    361     SET(c, d, a, b,  2, 15, T63);
    362     SET(b, c, d, a,  9, 21, T64);
    363 #undef SET
    364 
    365      /* Then perform the following additions. (That is increment each
    366         of the four registers by the value it had before this block
    367         was started.) */
    368     pms->abcd[0] += a;
    369     pms->abcd[1] += b;
    370     pms->abcd[2] += c;
    371     pms->abcd[3] += d;
    372 }
    373 
    374 void
    375 md5_init(md5_state_t *pms)
    376 {
    377     pms->count[0] = pms->count[1] = 0;
    378     pms->abcd[0] = 0x67452301;
    379     pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
    380     pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
    381     pms->abcd[3] = 0x10325476;
    382 }
    383 
    384 void
    385 md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
    386 {
    387     const md5_byte_t *p = data;
    388     int left = nbytes;
    389     int offset = (pms->count[0] >> 3) & 63;
    390     md5_word_t nbits = (md5_word_t)(nbytes << 3);
    391 
    392     if (nbytes <= 0)
    393 	return;
    394 
    395     /* Update the message length. */
    396     pms->count[1] += nbytes >> 29;
    397     pms->count[0] += nbits;
    398     if (pms->count[0] < nbits)
    399 	pms->count[1]++;
    400 
    401     /* Process an initial partial block. */
    402     if (offset) {
    403 	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
    404 
    405 	memcpy(pms->buf + offset, p, copy);
    406 	if (offset + copy < 64)
    407 	    return;
    408 	p += copy;
    409 	left -= copy;
    410 	md5_process(pms, pms->buf);
    411     }
    412 
    413     /* Process full blocks. */
    414     for (; left >= 64; p += 64, left -= 64)
    415 	md5_process(pms, p);
    416 
    417     /* Process a final partial block. */
    418     if (left)
    419 	memcpy(pms->buf, p, left);
    420 }
    421 
    422 void
    423 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
    424 {
    425     static const md5_byte_t pad[64] = {
    426 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    427 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    428 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    429 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    430     };
    431     md5_byte_t data[8];
    432     int i;
    433 
    434     /* Save the length before padding. */
    435     for (i = 0; i < 8; ++i)
    436 	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
    437     /* Pad to 56 bytes mod 64. */
    438     md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
    439     /* Append the length. */
    440     md5_append(pms, data, 8);
    441     for (i = 0; i < 16; ++i)
    442 	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
    443 }
    444 
    445 
    446 
    447 //
    448 // --- PTypes' wrapper class -----------------------------------------------
    449 //
    450 
    451 
    452 outmd5::outmd5(outstm* istm): outfilter(istm, 0)
    453 {
    454     memset(&ctx, 0, sizeof ctx);
    455     memset(digest, 0, sizeof digest);
    456 }
    457 
    458 
    459 outmd5::~outmd5() 
    460 {
    461     close();
    462 }
    463 
    464 
    465 void outmd5::doopen()
    466 {
    467     outfilter::doopen();
    468     memset(digest, 0, sizeof digest);
    469     md5_init(&ctx);
    470 }
    471 
    472 
    473 void outmd5::doclose()
    474 {
    475     md5_finish(&ctx, (unsigned char*)digest);
    476     outfilter::doclose();
    477 }
    478 
    479 
    480 int outmd5::dorawwrite(const char* buf, int count)
    481 {
    482     if (count > 0)
    483     {
    484         md5_append(&ctx, (const unsigned char*)buf, (unsigned)count);
    485         if (stm != nil)
    486             stm->write(buf, count);
    487         return count;
    488     }
    489     else
    490         return 0;
    491 }
    492 
    493 
    494 string outmd5::get_streamname()
    495 {
    496     return "MD5";
    497 }
    498 
    499 
    500 string outmd5::get_digest()
    501 {
    502     close();
    503     string result;
    504     // the first 120 bits are divided into 24-bit portions;
    505     // each portion is represented with 4 characters from the base64 set
    506     for (int i = 0; i <= 12; i += 3)
    507     {
    508         long v = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2];
    509         result += itostring(large(v), 64, 4);
    510     }
    511     // the last byte is complemented with 4 zero bits to form
    512     // the last two base64 characters
    513     return result + itostring(large(digest[15] << 4), 64, 2);
    514 }
    515 
    516 
    517 }