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
body(MD5_CTX * ctx,const void * data,ulong_t size)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
MD5_Init(MD5_CTX * ctx)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
MD5_Update(MD5_CTX * ctx,const void * data,ulong_t size)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
MD5_Final(unsigned char * result,MD5_CTX * ctx)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
md5_hash(const void * data,uptr size)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