• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
body(MD5_CTX * ctx,void * data,ulong_t size)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 
MD5_Init(MD5_CTX * ctx)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 
MD5_Update(MD5_CTX * ctx,void * data,ulong_t size)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 
MD5_Final(unsigned char * result,MD5_CTX * ctx)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 
md5_hash(const void * data,uptr size)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