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