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/StringRef.h" 32 #include "llvm/Support/Endian.h" 33 #include <array> 34 #include <cstdint> 35 36 namespace llvm { 37 38 template <unsigned N> class SmallString; 39 template <typename T> class ArrayRef; 40 41 class MD5 { 42 public: 43 struct MD5Result : public std::array<uint8_t, 16> { 44 SmallString<32> digest() const; 45 46 uint64_t low() const { 47 // Our MD5 implementation returns the result in little endian, so the low 48 // word is first. 49 using namespace support; 50 return endian::read<uint64_t, llvm::endianness::little>(data()); 51 } 52 53 uint64_t high() const { 54 using namespace support; 55 return endian::read<uint64_t, llvm::endianness::little>(data() + 8); 56 } 57 std::pair<uint64_t, uint64_t> words() const { 58 using namespace support; 59 return std::make_pair(high(), low()); 60 } 61 }; 62 63 MD5(); 64 65 /// Updates the hash for the byte stream provided. 66 void update(ArrayRef<uint8_t> Data); 67 68 /// Updates the hash for the StringRef provided. 69 void update(StringRef Str); 70 71 /// Finishes off the hash and puts the result in result. 72 void final(MD5Result &Result); 73 74 /// Finishes off the hash, and returns the 16-byte hash data. 75 MD5Result final(); 76 77 /// Finishes off the hash, and returns the 16-byte hash data. 78 /// This is suitable for getting the MD5 at any time without invalidating the 79 /// internal state, so that more calls can be made into `update`. 80 MD5Result result(); 81 82 /// Translates the bytes in \p Res to a hex string that is 83 /// deposited into \p Str. The result will be of length 32. 84 static void stringifyResult(MD5Result &Result, SmallVectorImpl<char> &Str); 85 86 /// Computes the hash for a given bytes. 87 static MD5Result hash(ArrayRef<uint8_t> Data); 88 89 private: 90 // Any 32-bit or wider unsigned integer data type will do. 91 typedef uint32_t MD5_u32plus; 92 93 // Internal State 94 struct { 95 MD5_u32plus a = 0x67452301; 96 MD5_u32plus b = 0xefcdab89; 97 MD5_u32plus c = 0x98badcfe; 98 MD5_u32plus d = 0x10325476; 99 MD5_u32plus hi = 0; 100 MD5_u32plus lo = 0; 101 uint8_t buffer[64]; 102 MD5_u32plus block[16]; 103 } InternalState; 104 105 const uint8_t *body(ArrayRef<uint8_t> Data); 106 }; 107 108 /// Helper to compute and return lower 64 bits of the given string's MD5 hash. 109 inline 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