1/* -*- C++ -*- 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/md5 9 * 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 is 14 * claimed, and the software is hereby placed in the public domain. 15 * In case this attempt to disclaim copyright and place the software in the 16 * public domain is deemed null and void, then the software is 17 * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the 18 * general public under the following terms: 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted. 22 * 23 * There's ABSOLUTELY NO WARRANTY, express or implied. 24 * 25 * See md5.c for more information. 26 */ 27 28#ifndef LLVM_SUPPORT_MD5_H 29#define LLVM_SUPPORT_MD5_H 30 31#include "llvm/ADT/SmallString.h" 32#include "llvm/ADT/StringRef.h" 33#include "llvm/Support/Endian.h" 34#include <array> 35#include <cstdint> 36 37namespace llvm { 38 39template <typename T> class ArrayRef; 40 41class MD5 { 42 // Any 32-bit or wider unsigned integer data type will do. 43 typedef uint32_t MD5_u32plus; 44 45 MD5_u32plus a = 0x67452301; 46 MD5_u32plus b = 0xefcdab89; 47 MD5_u32plus c = 0x98badcfe; 48 MD5_u32plus d = 0x10325476; 49 MD5_u32plus hi = 0; 50 MD5_u32plus lo = 0; 51 uint8_t buffer[64]; 52 MD5_u32plus block[16]; 53 54public: 55 struct MD5Result { 56 std::array<uint8_t, 16> Bytes; 57 58 operator std::array<uint8_t, 16>() const { return Bytes; } 59 60 const uint8_t &operator[](size_t I) const { return Bytes[I]; } 61 uint8_t &operator[](size_t I) { return Bytes[I]; } 62 63 SmallString<32> digest() const; 64 65 uint64_t low() const { 66 // Our MD5 implementation returns the result in little endian, so the low 67 // word is first. 68 using namespace support; 69 return endian::read<uint64_t, little, unaligned>(Bytes.data()); 70 } 71 72 uint64_t high() const { 73 using namespace support; 74 return endian::read<uint64_t, little, unaligned>(Bytes.data() + 8); 75 } 76 std::pair<uint64_t, uint64_t> words() const { 77 using namespace support; 78 return std::make_pair(high(), low()); 79 } 80 }; 81 82 MD5(); 83 84 /// Updates the hash for the byte stream provided. 85 void update(ArrayRef<uint8_t> Data); 86 87 /// Updates the hash for the StringRef provided. 88 void update(StringRef Str); 89 90 /// Finishes off the hash and puts the result in result. 91 void final(MD5Result &Result); 92 93 /// Translates the bytes in \p Res to a hex string that is 94 /// deposited into \p Str. The result will be of length 32. 95 static void stringifyResult(MD5Result &Result, SmallString<32> &Str); 96 97 /// Computes the hash for a given bytes. 98 static std::array<uint8_t, 16> hash(ArrayRef<uint8_t> Data); 99 100private: 101 const uint8_t *body(ArrayRef<uint8_t> Data); 102}; 103 104inline bool operator==(const MD5::MD5Result &LHS, const MD5::MD5Result &RHS) { 105 return LHS.Bytes == RHS.Bytes; 106} 107 108/// Helper to compute and return lower 64 bits of the given string's MD5 hash. 109inline uint64_t MD5Hash(StringRef Str) { 110 using namespace support; 111 112 MD5 Hash; 113 Hash.update(Str); 114 MD5::MD5Result Result; 115 Hash.final(Result); 116 // Return the least significant word. 117 return Result.low(); 118} 119 120} // end namespace llvm 121 122#endif // LLVM_SUPPORT_MD5_H 123