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