brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · 72857b7 Raw
251 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of ThreadSanitizer (TSan), a race detector.10//11//===----------------------------------------------------------------------===//12#include "tsan_defs.h"13 14namespace __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 31typedef unsigned int MD5_u32plus;32typedef unsigned long ulong_t;33 34typedef 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 41static 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 F142#undef G143#undef H144#undef I145#undef STEP146#undef SET147#undef GET148 149void 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 159void 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 192void 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 242MD5Hash 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 __tsan251