1 //===-- tsan_md5.cc -------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //===----------------------------------------------------------------------===//
12 #include "tsan_defs.h"
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)))
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)))); \
27 (*(const MD5_u32plus *)&ptr[(n) * 4])
31 typedef unsigned int MD5_u32plus;
32 typedef unsigned long ulong_t; // NOLINT
36 MD5_u32plus a, b, c, d;
37 unsigned char buffer[64];
38 MD5_u32plus block[16];
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;
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)
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)
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)
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)
131 } while (size -= 64);
149 void MD5_Init(MD5_CTX *ctx) {
159 void MD5_Update(MD5_CTX *ctx, const void *data, ulong_t size) {
160 MD5_u32plus saved_lo;
164 if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
166 ctx->hi += size >> 29;
168 used = saved_lo & 0x3f;
174 internal_memcpy(&ctx->buffer[used], data, size);
178 internal_memcpy(&ctx->buffer[used], data, free);
179 data = (const unsigned char *)data + free;
181 body(ctx, ctx->buffer, 64);
185 data = body(ctx, data, size & ~(ulong_t)0x3f);
189 internal_memcpy(ctx->buffer, data, size);
192 void MD5_Final(unsigned char *result, MD5_CTX *ctx) {
195 used = ctx->lo & 0x3f;
197 ctx->buffer[used++] = 0x80;
202 internal_memset(&ctx->buffer[used], 0, free);
203 body(ctx, ctx->buffer, 64);
208 internal_memset(&ctx->buffer[used], 0, free - 8);
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;
220 body(ctx, ctx->buffer, 64);
223 result[1] = ctx->a >> 8;
224 result[2] = ctx->a >> 16;
225 result[3] = ctx->a >> 24;
227 result[5] = ctx->b >> 8;
228 result[6] = ctx->b >> 16;
229 result[7] = ctx->b >> 24;
231 result[9] = ctx->c >> 8;
232 result[10] = ctx->c >> 16;
233 result[11] = ctx->c >> 24;
235 result[13] = ctx->d >> 8;
236 result[14] = ctx->d >> 16;
237 result[15] = ctx->d >> 24;
239 internal_memset(ctx, 0, sizeof(*ctx));
242 MD5Hash md5_hash(const void *data, uptr size) {
246 MD5_Update(&ctx, data, size);
247 MD5_Final((unsigned char*)&res.hash[0], &ctx);
250 } // namespace __tsan