tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

md5_utils.c (8265B)


      1 /*
      2 * This code implements the MD5 message-digest algorithm.
      3 * The algorithm is due to Ron Rivest.  This code was
      4 * written by Colin Plumb in 1993, no copyright is claimed.
      5 * This code is in the public domain; do with it what you wish.
      6 *
      7 * Equivalent code is available from RSA Data Security, Inc.
      8 * This code has been tested against that, and is equivalent,
      9 * except that you don't need to include two pages of legalese
     10 * with every copy.
     11 *
     12 * To compute the message digest of a chunk of bytes, declare an
     13 * MD5Context structure, pass it to MD5Init, call MD5Update as
     14 * needed on buffers full of bytes, and then call MD5Final, which
     15 * will fill a supplied 16-byte array with the digest.
     16 *
     17 * Changed so as no longer to depend on Colin Plumb's `usual.h' header
     18 * definitions
     19 *  - Ian Jackson <ian@chiark.greenend.org.uk>.
     20 * Still in the public domain.
     21 */
     22 
     23 #include <string.h> /* for memcpy() */
     24 
     25 #include "common/md5_utils.h"
     26 
     27 static void byteSwap(UWORD32 *buf, unsigned words) {
     28  md5byte *p;
     29 
     30  /* Only swap bytes for big endian machines */
     31  int i = 1;
     32 
     33  if (*(char *)&i == 1) return;
     34 
     35  p = (md5byte *)buf;
     36 
     37  do {
     38    *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 |
     39             ((unsigned)p[1] << 8 | p[0]);
     40    p += 4;
     41  } while (--words);
     42 }
     43 
     44 /*
     45 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
     46 * initialization constants.
     47 */
     48 void MD5Init(struct MD5Context *ctx) {
     49  ctx->buf[0] = 0x67452301;
     50  ctx->buf[1] = 0xefcdab89;
     51  ctx->buf[2] = 0x98badcfe;
     52  ctx->buf[3] = 0x10325476;
     53 
     54  ctx->bytes[0] = 0;
     55  ctx->bytes[1] = 0;
     56 }
     57 
     58 /*
     59 * Update context to reflect the concatenation of another buffer full
     60 * of bytes.
     61 */
     62 void MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
     63  UWORD32 t;
     64 
     65  /* Update byte count */
     66 
     67  t = ctx->bytes[0];
     68 
     69  if ((ctx->bytes[0] = t + len) < t)
     70    ctx->bytes[1]++; /* Carry from low to high */
     71 
     72  t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
     73 
     74  if (t > len) {
     75    memcpy((md5byte *)ctx->in + 64 - t, buf, len);
     76    return;
     77  }
     78 
     79  /* First chunk is an odd size */
     80  memcpy((md5byte *)ctx->in + 64 - t, buf, t);
     81  byteSwap(ctx->in, 16);
     82  MD5Transform(ctx->buf, ctx->in);
     83  buf += t;
     84  len -= t;
     85 
     86  /* Process data in 64-byte chunks */
     87  while (len >= 64) {
     88    memcpy(ctx->in, buf, 64);
     89    byteSwap(ctx->in, 16);
     90    MD5Transform(ctx->buf, ctx->in);
     91    buf += 64;
     92    len -= 64;
     93  }
     94 
     95  /* Handle any remaining bytes of data. */
     96  memcpy(ctx->in, buf, len);
     97 }
     98 
     99 /*
    100 * Final wrapup - pad to 64-byte boundary with the bit pattern
    101 * 1 0* (64-bit count of bits processed, MSB-first)
    102 */
    103 void MD5Final(md5byte digest[16], struct MD5Context *ctx) {
    104  int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
    105  md5byte *p = (md5byte *)ctx->in + count;
    106 
    107  /* Set the first char of padding to 0x80.  There is always room. */
    108  *p++ = 0x80;
    109 
    110  /* Bytes of padding needed to make 56 bytes (-8..55) */
    111  count = 56 - 1 - count;
    112 
    113  if (count < 0) { /* Padding forces an extra block */
    114    memset(p, 0, count + 8);
    115    byteSwap(ctx->in, 16);
    116    MD5Transform(ctx->buf, ctx->in);
    117    p = (md5byte *)ctx->in;
    118    count = 56;
    119  }
    120 
    121  memset(p, 0, count);
    122  byteSwap(ctx->in, 14);
    123 
    124  /* Append length in bits and transform */
    125  ctx->in[14] = ctx->bytes[0] << 3;
    126  ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
    127  MD5Transform(ctx->buf, ctx->in);
    128 
    129  byteSwap(ctx->buf, 4);
    130  memcpy(digest, ctx->buf, 16);
    131  memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
    132 }
    133 
    134 #ifndef ASM_MD5
    135 
    136 /* The four core functions - F1 is optimized somewhat */
    137 
    138 /* #define F1(x, y, z) (x & y | ~x & z) */
    139 #define F1(x, y, z) (z ^ (x & (y ^ z)))
    140 #define F2(x, y, z) F1(z, x, y)
    141 #define F3(x, y, z) (x ^ y ^ z)
    142 #define F4(x, y, z) (y ^ (x | ~z))
    143 
    144 /* This is the central step in the MD5 algorithm. */
    145 #define MD5STEP(f, w, x, y, z, in, s) \
    146  (w += f(x, y, z) + in, w = (w << s | w >> (32 - s)) + x)
    147 
    148 #if defined(__clang__) && defined(__has_attribute)
    149 #if __has_attribute(no_sanitize)
    150 #define AOM_NO_UNSIGNED_OVERFLOW_CHECK \
    151  __attribute__((no_sanitize("unsigned-integer-overflow")))
    152 #endif
    153 #if __clang_major__ >= 12
    154 #define VPX_NO_UNSIGNED_SHIFT_CHECK \
    155  __attribute__((no_sanitize("unsigned-shift-base")))
    156 #endif  // __clang__ >= 12
    157 #endif  // __clang__
    158 
    159 #ifndef AOM_NO_UNSIGNED_OVERFLOW_CHECK
    160 #define AOM_NO_UNSIGNED_OVERFLOW_CHECK
    161 #endif
    162 #ifndef AOM_NO_UNSIGNED_SHIFT_CHECK
    163 #define AOM_NO_UNSIGNED_SHIFT_CHECK
    164 #endif
    165 
    166 /*
    167 * The core of the MD5 algorithm, this alters an existing MD5 hash to
    168 * reflect the addition of 16 longwords of new data.  MD5Update blocks
    169 * the data and converts bytes into longwords for this routine.
    170 */
    171 AOM_NO_UNSIGNED_OVERFLOW_CHECK AOM_NO_UNSIGNED_SHIFT_CHECK void MD5Transform(
    172    UWORD32 buf[4], UWORD32 const in[16]) {
    173  register UWORD32 a, b, c, d;
    174 
    175  a = buf[0];
    176  b = buf[1];
    177  c = buf[2];
    178  d = buf[3];
    179 
    180  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
    181  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
    182  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
    183  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
    184  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
    185  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
    186  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
    187  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
    188  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
    189  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
    190  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
    191  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
    192  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
    193  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
    194  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
    195  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
    196 
    197  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
    198  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
    199  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
    200  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
    201  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
    202  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
    203  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
    204  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
    205  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
    206  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
    207  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
    208  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
    209  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
    210  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
    211  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
    212  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
    213 
    214  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
    215  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
    216  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
    217  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
    218  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
    219  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
    220  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
    221  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
    222  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
    223  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
    224  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
    225  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
    226  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
    227  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
    228  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
    229  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
    230 
    231  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
    232  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
    233  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
    234  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
    235  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
    236  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
    237  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
    238  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
    239  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
    240  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
    241  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
    242  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
    243  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
    244  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
    245  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
    246  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
    247 
    248  buf[0] += a;
    249  buf[1] += b;
    250  buf[2] += c;
    251  buf[3] += d;
    252 }
    253 
    254 #undef AOM_NO_UNSIGNED_OVERFLOW_CHECK
    255 #undef AOM_NO_UNSIGNED_SHIFT_CHECK
    256 
    257 #endif