]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_md5.cc
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / compiler-rt / lib / tsan / rtl / tsan_md5.cc
1 //===-- tsan_md5.cc -------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
10 //
11 //===----------------------------------------------------------------------===//
12 #include "tsan_defs.h"
13
14 namespace __tsan {
15
16 #define F(x, y, z)      ((z) ^ ((x) & ((y) ^ (z))))
17 #define G(x, y, z)      ((y) ^ ((z) & ((x) ^ (y))))
18 #define H(x, y, z)      ((x) ^ (y) ^ (z))
19 #define I(x, y, z)      ((y) ^ ((x) | ~(z)))
20
21 #define STEP(f, a, b, c, d, x, t, s) \
22   (a) += f((b), (c), (d)) + (x) + (t); \
23   (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
24   (a) += (b);
25
26 #define SET(n) \
27   (*(const MD5_u32plus *)&ptr[(n) * 4])
28 #define GET(n) \
29   SET(n)
30
31 typedef unsigned int MD5_u32plus;
32 typedef unsigned long ulong_t;  // NOLINT
33
34 typedef struct {
35   MD5_u32plus lo, hi;
36   MD5_u32plus a, b, c, d;
37   unsigned char buffer[64];
38   MD5_u32plus block[16];
39 } MD5_CTX;
40
41 static const void *body(MD5_CTX *ctx, const void *data, ulong_t size) {
42   const unsigned char *ptr = (const unsigned char *)data;
43   MD5_u32plus a, b, c, d;
44   MD5_u32plus saved_a, saved_b, saved_c, saved_d;
45
46   a = ctx->a;
47   b = ctx->b;
48   c = ctx->c;
49   d = ctx->d;
50
51   do {
52     saved_a = a;
53     saved_b = b;
54     saved_c = c;
55     saved_d = d;
56
57     STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
58     STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
59     STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
60     STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
61     STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
62     STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
63     STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
64     STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
65     STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
66     STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
67     STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
68     STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
69     STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
70     STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
71     STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
72     STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
73
74     STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
75     STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
76     STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
77     STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
78     STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
79     STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
80     STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
81     STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
82     STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
83     STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
84     STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
85     STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
86     STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
87     STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
88     STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
89     STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
90
91     STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
92     STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
93     STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
94     STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
95     STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
96     STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
97     STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
98     STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
99     STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
100     STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
101     STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
102     STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
103     STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
104     STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
105     STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
106     STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
107
108     STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
109     STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
110     STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
111     STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
112     STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
113     STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
114     STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
115     STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
116     STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
117     STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
118     STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
119     STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
120     STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
121     STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
122     STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
123     STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
124
125     a += saved_a;
126     b += saved_b;
127     c += saved_c;
128     d += saved_d;
129
130     ptr += 64;
131   } while (size -= 64);
132
133   ctx->a = a;
134   ctx->b = b;
135   ctx->c = c;
136   ctx->d = d;
137
138   return ptr;
139 }
140
141 #undef F
142 #undef G
143 #undef H
144 #undef I
145 #undef STEP
146 #undef SET
147 #undef GET
148
149 void MD5_Init(MD5_CTX *ctx) {
150   ctx->a = 0x67452301;
151   ctx->b = 0xefcdab89;
152   ctx->c = 0x98badcfe;
153   ctx->d = 0x10325476;
154
155   ctx->lo = 0;
156   ctx->hi = 0;
157 }
158
159 void MD5_Update(MD5_CTX *ctx, const void *data, ulong_t size) {
160   MD5_u32plus saved_lo;
161   ulong_t used, free;
162
163   saved_lo = ctx->lo;
164   if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
165     ctx->hi++;
166   ctx->hi += size >> 29;
167
168   used = saved_lo & 0x3f;
169
170   if (used) {
171     free = 64 - used;
172
173     if (size < free) {
174       internal_memcpy(&ctx->buffer[used], data, size);
175       return;
176     }
177
178     internal_memcpy(&ctx->buffer[used], data, free);
179     data = (const unsigned char *)data + free;
180     size -= free;
181     body(ctx, ctx->buffer, 64);
182   }
183
184   if (size >= 64) {
185     data = body(ctx, data, size & ~(ulong_t)0x3f);
186     size &= 0x3f;
187   }
188
189   internal_memcpy(ctx->buffer, data, size);
190 }
191
192 void MD5_Final(unsigned char *result, MD5_CTX *ctx) {
193   ulong_t used, free;
194
195   used = ctx->lo & 0x3f;
196
197   ctx->buffer[used++] = 0x80;
198
199   free = 64 - used;
200
201   if (free < 8) {
202     internal_memset(&ctx->buffer[used], 0, free);
203     body(ctx, ctx->buffer, 64);
204     used = 0;
205     free = 64;
206   }
207
208   internal_memset(&ctx->buffer[used], 0, free - 8);
209
210   ctx->lo <<= 3;
211   ctx->buffer[56] = ctx->lo;
212   ctx->buffer[57] = ctx->lo >> 8;
213   ctx->buffer[58] = ctx->lo >> 16;
214   ctx->buffer[59] = ctx->lo >> 24;
215   ctx->buffer[60] = ctx->hi;
216   ctx->buffer[61] = ctx->hi >> 8;
217   ctx->buffer[62] = ctx->hi >> 16;
218   ctx->buffer[63] = ctx->hi >> 24;
219
220   body(ctx, ctx->buffer, 64);
221
222   result[0] = ctx->a;
223   result[1] = ctx->a >> 8;
224   result[2] = ctx->a >> 16;
225   result[3] = ctx->a >> 24;
226   result[4] = ctx->b;
227   result[5] = ctx->b >> 8;
228   result[6] = ctx->b >> 16;
229   result[7] = ctx->b >> 24;
230   result[8] = ctx->c;
231   result[9] = ctx->c >> 8;
232   result[10] = ctx->c >> 16;
233   result[11] = ctx->c >> 24;
234   result[12] = ctx->d;
235   result[13] = ctx->d >> 8;
236   result[14] = ctx->d >> 16;
237   result[15] = ctx->d >> 24;
238
239   internal_memset(ctx, 0, sizeof(*ctx));
240 }
241
242 MD5Hash md5_hash(const void *data, uptr size) {
243   MD5Hash res;
244   MD5_CTX ctx;
245   MD5_Init(&ctx);
246   MD5_Update(&ctx, data, size);
247   MD5_Final((unsigned char*)&res.hash[0], &ctx);
248   return res;
249 }
250 }  // namespace __tsan