Home | History | Annotate | Download | only in rtl
      1 //===-- tsan_md5.cc -------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of ThreadSanitizer (TSan), a race detector.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 #include "tsan_defs.h"
     14 
     15 namespace __tsan {
     16 
     17 #define F(x, y, z)      ((z) ^ ((x) & ((y) ^ (z))))
     18 #define G(x, y, z)      ((y) ^ ((z) & ((x) ^ (y))))
     19 #define H(x, y, z)      ((x) ^ (y) ^ (z))
     20 #define I(x, y, z)      ((y) ^ ((x) | ~(z)))
     21 
     22 #define STEP(f, a, b, c, d, x, t, s) \
     23   (a) += f((b), (c), (d)) + (x) + (t); \
     24   (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
     25   (a) += (b);
     26 
     27 #define SET(n) \
     28   (*(const MD5_u32plus *)&ptr[(n) * 4])
     29 #define GET(n) \
     30   SET(n)
     31 
     32 typedef unsigned int MD5_u32plus;
     33 typedef unsigned long ulong_t;  // NOLINT
     34 
     35 typedef struct {
     36   MD5_u32plus lo, hi;
     37   MD5_u32plus a, b, c, d;
     38   unsigned char buffer[64];
     39   MD5_u32plus block[16];
     40 } MD5_CTX;
     41 
     42 static const void *body(MD5_CTX *ctx, const void *data, ulong_t size) {
     43   const unsigned char *ptr = (const unsigned char *)data;
     44   MD5_u32plus a, b, c, d;
     45   MD5_u32plus saved_a, saved_b, saved_c, saved_d;
     46 
     47   a = ctx->a;
     48   b = ctx->b;
     49   c = ctx->c;
     50   d = ctx->d;
     51 
     52   do {
     53     saved_a = a;
     54     saved_b = b;
     55     saved_c = c;
     56     saved_d = d;
     57 
     58     STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
     59     STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
     60     STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
     61     STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
     62     STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
     63     STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
     64     STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
     65     STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
     66     STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
     67     STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
     68     STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
     69     STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
     70     STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
     71     STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
     72     STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
     73     STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
     74 
     75     STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
     76     STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
     77     STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
     78     STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
     79     STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
     80     STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
     81     STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
     82     STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
     83     STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
     84     STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
     85     STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
     86     STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
     87     STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
     88     STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
     89     STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
     90     STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
     91 
     92     STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
     93     STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
     94     STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
     95     STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
     96     STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
     97     STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
     98     STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
     99     STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
    100     STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
    101     STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
    102     STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
    103     STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
    104     STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
    105     STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
    106     STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
    107     STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
    108 
    109     STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
    110     STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
    111     STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
    112     STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
    113     STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
    114     STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
    115     STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
    116     STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
    117     STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
    118     STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
    119     STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
    120     STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
    121     STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
    122     STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
    123     STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
    124     STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
    125 
    126     a += saved_a;
    127     b += saved_b;
    128     c += saved_c;
    129     d += saved_d;
    130 
    131     ptr += 64;
    132   } while (size -= 64);
    133 
    134   ctx->a = a;
    135   ctx->b = b;
    136   ctx->c = c;
    137   ctx->d = d;
    138 
    139   return ptr;
    140 }
    141 
    142 void MD5_Init(MD5_CTX *ctx) {
    143   ctx->a = 0x67452301;
    144   ctx->b = 0xefcdab89;
    145   ctx->c = 0x98badcfe;
    146   ctx->d = 0x10325476;
    147 
    148   ctx->lo = 0;
    149   ctx->hi = 0;
    150 }
    151 
    152 void MD5_Update(MD5_CTX *ctx, const void *data, ulong_t size) {
    153   MD5_u32plus saved_lo;
    154   ulong_t used, free;
    155 
    156   saved_lo = ctx->lo;
    157   if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
    158     ctx->hi++;
    159   ctx->hi += size >> 29;
    160 
    161   used = saved_lo & 0x3f;
    162 
    163   if (used) {
    164     free = 64 - used;
    165 
    166     if (size < free) {
    167       internal_memcpy(&ctx->buffer[used], data, size);
    168       return;
    169     }
    170 
    171     internal_memcpy(&ctx->buffer[used], data, free);
    172     data = (const unsigned char *)data + free;
    173     size -= free;
    174     body(ctx, ctx->buffer, 64);
    175   }
    176 
    177   if (size >= 64) {
    178     data = body(ctx, data, size & ~(ulong_t)0x3f);
    179     size &= 0x3f;
    180   }
    181 
    182   internal_memcpy(ctx->buffer, data, size);
    183 }
    184 
    185 void MD5_Final(unsigned char *result, MD5_CTX *ctx) {
    186   ulong_t used, free;
    187 
    188   used = ctx->lo & 0x3f;
    189 
    190   ctx->buffer[used++] = 0x80;
    191 
    192   free = 64 - used;
    193 
    194   if (free < 8) {
    195     internal_memset(&ctx->buffer[used], 0, free);
    196     body(ctx, ctx->buffer, 64);
    197     used = 0;
    198     free = 64;
    199   }
    200 
    201   internal_memset(&ctx->buffer[used], 0, free - 8);
    202 
    203   ctx->lo <<= 3;
    204   ctx->buffer[56] = ctx->lo;
    205   ctx->buffer[57] = ctx->lo >> 8;
    206   ctx->buffer[58] = ctx->lo >> 16;
    207   ctx->buffer[59] = ctx->lo >> 24;
    208   ctx->buffer[60] = ctx->hi;
    209   ctx->buffer[61] = ctx->hi >> 8;
    210   ctx->buffer[62] = ctx->hi >> 16;
    211   ctx->buffer[63] = ctx->hi >> 24;
    212 
    213   body(ctx, ctx->buffer, 64);
    214 
    215   result[0] = ctx->a;
    216   result[1] = ctx->a >> 8;
    217   result[2] = ctx->a >> 16;
    218   result[3] = ctx->a >> 24;
    219   result[4] = ctx->b;
    220   result[5] = ctx->b >> 8;
    221   result[6] = ctx->b >> 16;
    222   result[7] = ctx->b >> 24;
    223   result[8] = ctx->c;
    224   result[9] = ctx->c >> 8;
    225   result[10] = ctx->c >> 16;
    226   result[11] = ctx->c >> 24;
    227   result[12] = ctx->d;
    228   result[13] = ctx->d >> 8;
    229   result[14] = ctx->d >> 16;
    230   result[15] = ctx->d >> 24;
    231 
    232   internal_memset(ctx, 0, sizeof(*ctx));
    233 }
    234 
    235 MD5Hash md5_hash(const void *data, uptr size) {
    236   MD5Hash res;
    237   MD5_CTX ctx;
    238   MD5_Init(&ctx);
    239   MD5_Update(&ctx, data, size);
    240   MD5_Final((unsigned char*)&res.hash[0], &ctx);
    241   return res;
    242 }
    243 }  // namespace __tsan
    244