Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_md5.cpp
35267 views
1
//===-- tsan_md5.cpp ------------------------------------------------------===//
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;
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
251
252