]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/tsan/rtl/tsan_md5.cc
Merge sync of head
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / tsan / rtl / tsan_md5.cc
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