brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.6 KiB · 32e2a2e Raw
306 lines · cpp
1/*2 * This code is derived from (original license follows):3 *4 * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.5 * MD5 Message-Digest Algorithm (RFC 1321).6 *7 * Homepage:8 * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md59 *10 * Author:11 * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>12 *13 * This software was written by Alexander Peslyak in 2001.  No copyright is14 * claimed, and the software is hereby placed in the public domain.15 * In case this attempt to disclaim copyright and place the software in the16 * public domain is deemed null and void, then the software is17 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the18 * general public under the following terms:19 *20 * Redistribution and use in source and binary forms, with or without21 * modification, are permitted.22 *23 * There's ABSOLUTELY NO WARRANTY, express or implied.24 *25 * (This is a heavily cut-down "BSD license".)26 *27 * This differs from Colin Plumb's older public domain implementation in that28 * no exactly 32-bit integer data type is required (any 32-bit or wider29 * unsigned integer data type will do), there's no compile-time endianness30 * configuration, and the function prototypes match OpenSSL's.  No code from31 * Colin Plumb's implementation has been reused; this comment merely compares32 * the properties of the two independent implementations.33 *34 * The primary goals of this implementation are portability and ease of use.35 * It is meant to be fast, but not as fast as possible.  Some known36 * optimizations are not included to reduce source code size and avoid37 * compile-time configuration.38 */39 40#include "llvm/Support/MD5.h"41#include "llvm/ADT/ArrayRef.h"42#include "llvm/ADT/SmallString.h"43#include "llvm/ADT/StringExtras.h"44#include "llvm/ADT/StringRef.h"45#include "llvm/Support/Endian.h"46#include <cstdint>47#include <cstring>48 49// The basic MD5 functions.50 51// F and G are optimized compared to their RFC 1321 definitions for52// architectures that lack an AND-NOT instruction, just like in Colin Plumb's53// implementation.54#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))55#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))56#define H(x, y, z) ((x) ^ (y) ^ (z))57#define I(x, y, z) ((y) ^ ((x) | ~(z)))58 59// The MD5 transformation for all four rounds.60#define STEP(f, a, b, c, d, x, t, s)                                           \61  (a) += f((b), (c), (d)) + (x) + (t);                                         \62  (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));                   \63  (a) += (b);64 65// SET reads 4 input bytes in little-endian byte order and stores them66// in a properly aligned word in host byte order.67#define SET(n)                                                                 \68  (InternalState.block[(n)] = (MD5_u32plus)ptr[(n)*4] |                        \69                              ((MD5_u32plus)ptr[(n)*4 + 1] << 8) |             \70                              ((MD5_u32plus)ptr[(n)*4 + 2] << 16) |            \71                              ((MD5_u32plus)ptr[(n)*4 + 3] << 24))72#define GET(n) (InternalState.block[(n)])73 74using namespace llvm;75 76/// This processes one or more 64-byte data blocks, but does NOT update77///the bit counters.  There are no alignment requirements.78const uint8_t *MD5::body(ArrayRef<uint8_t> Data) {79  const uint8_t *ptr;80  MD5_u32plus a, b, c, d;81  MD5_u32plus saved_a, saved_b, saved_c, saved_d;82  unsigned long Size = Data.size();83 84  ptr = Data.data();85 86  a = InternalState.a;87  b = InternalState.b;88  c = InternalState.c;89  d = InternalState.d;90 91  do {92    saved_a = a;93    saved_b = b;94    saved_c = c;95    saved_d = d;96 97    // Round 198    STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)99    STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)100    STEP(F, c, d, a, b, SET(2), 0x242070db, 17)101    STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)102    STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)103    STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)104    STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)105    STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)106    STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)107    STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)108    STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)109    STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)110    STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)111    STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)112    STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)113    STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)114 115    // Round 2116    STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)117    STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)118    STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)119    STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)120    STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)121    STEP(G, d, a, b, c, GET(10), 0x02441453, 9)122    STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)123    STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)124    STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)125    STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)126    STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)127    STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)128    STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)129    STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)130    STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)131    STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)132 133    // Round 3134    STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)135    STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)136    STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)137    STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)138    STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)139    STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)140    STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)141    STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)142    STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)143    STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)144    STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)145    STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)146    STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)147    STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)148    STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)149    STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)150 151    // Round 4152    STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)153    STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)154    STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)155    STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)156    STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)157    STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)158    STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)159    STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)160    STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)161    STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)162    STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)163    STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)164    STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)165    STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)166    STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)167    STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)168 169    a += saved_a;170    b += saved_b;171    c += saved_c;172    d += saved_d;173 174    ptr += 64;175  } while (Size -= 64);176 177  InternalState.a = a;178  InternalState.b = b;179  InternalState.c = c;180  InternalState.d = d;181 182  return ptr;183}184 185MD5::MD5() = default;186 187/// Incrementally add the bytes in \p Data to the hash.188void MD5::update(ArrayRef<uint8_t> Data) {189  MD5_u32plus saved_lo;190  unsigned long used, free;191  const uint8_t *Ptr = Data.data();192  unsigned long Size = Data.size();193 194  saved_lo = InternalState.lo;195  if ((InternalState.lo = (saved_lo + Size) & 0x1fffffff) < saved_lo)196    InternalState.hi++;197  InternalState.hi += Size >> 29;198 199  used = saved_lo & 0x3f;200 201  if (used) {202    free = 64 - used;203 204    if (Size < free) {205      memcpy(&InternalState.buffer[used], Ptr, Size);206      return;207    }208 209    memcpy(&InternalState.buffer[used], Ptr, free);210    Ptr = Ptr + free;211    Size -= free;212    body(ArrayRef(InternalState.buffer, 64));213  }214 215  if (Size >= 64) {216    Ptr = body(ArrayRef(Ptr, Size & ~(unsigned long)0x3f));217    Size &= 0x3f;218  }219 220  memcpy(InternalState.buffer, Ptr, Size);221}222 223/// Add the bytes in the StringRef \p Str to the hash.224// Note that this isn't a string and so this won't include any trailing NULL225// bytes.226void MD5::update(StringRef Str) {227  ArrayRef<uint8_t> SVal((const uint8_t *)Str.data(), Str.size());228  update(SVal);229}230 231/// Finish the hash and place the resulting hash into \p result.232/// \param Result is assumed to be a minimum of 16-bytes in size.233void MD5::final(MD5Result &Result) {234  unsigned long used, free;235 236  used = InternalState.lo & 0x3f;237 238  InternalState.buffer[used++] = 0x80;239 240  free = 64 - used;241 242  if (free < 8) {243    memset(&InternalState.buffer[used], 0, free);244    body(ArrayRef(InternalState.buffer, 64));245    used = 0;246    free = 64;247  }248 249  memset(&InternalState.buffer[used], 0, free - 8);250 251  InternalState.lo <<= 3;252  support::endian::write32le(&InternalState.buffer[56], InternalState.lo);253  support::endian::write32le(&InternalState.buffer[60], InternalState.hi);254 255  body(ArrayRef(InternalState.buffer, 64));256 257  support::endian::write32le(&Result[0], InternalState.a);258  support::endian::write32le(&Result[4], InternalState.b);259  support::endian::write32le(&Result[8], InternalState.c);260  support::endian::write32le(&Result[12], InternalState.d);261}262 263MD5::MD5Result MD5::final() {264  MD5Result Result;265  final(Result);266  return Result;267}268 269MD5::MD5Result MD5::result() {270  auto StateToRestore = InternalState;271 272  auto Hash = final();273 274  // Restore the state275  InternalState = StateToRestore;276 277  return Hash;278}279 280SmallString<32> MD5::MD5Result::digest() const {281  SmallString<32> Str;282  toHex(*this, /*LowerCase*/ true, Str);283  return Str;284}285 286void MD5::stringifyResult(MD5Result &Result, SmallVectorImpl<char> &Str) {287  toHex(Result, /*LowerCase*/ true, Str);288}289 290MD5::MD5Result MD5::hash(ArrayRef<uint8_t> Data) {291  MD5 Hash;292  Hash.update(Data);293  MD5::MD5Result Res;294  Hash.final(Res);295 296  return Res;297}298 299#undef F300#undef G301#undef H302#undef I303#undef STEP304#undef SET305#undef GET306