1 /* 2 This code is written by kerukuro and released into public domain. 3 */ 4 5 #ifndef DIGESTPP_PROVIDERS_MD5_HPP 6 #define DIGESTPP_PROVIDERS_MD5_HPP 7 8 #include "../../detail/functions.hpp" 9 #include "../../detail/absorb_data.hpp" 10 #include "constants/md5_constants.hpp" 11 #include <array> 12 13 namespace digestpp 14 { 15 16 namespace detail 17 { 18 19 namespace md5_functions 20 { roundf(int round,uint32_t & a,uint32_t & b,uint32_t & c,uint32_t & d,const uint32_t * M)21 static inline void roundf(int round, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, const uint32_t* M) 22 { 23 a = b + rotate_left(a + (d ^ (b & (c ^ d))) + md5_constants<void>::K[round] + M[round], 24 md5_constants<void>::S[round]); 25 } 26 roundg(int round,uint32_t & a,uint32_t & b,uint32_t & c,uint32_t & d,const uint32_t * M)27 static inline void roundg(int round, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, const uint32_t* M) 28 { 29 a = b + rotate_left(a + (c ^ (d & (b ^ c))) + md5_constants<void>::K[round] + M[(5 * round + 1) % 16], 30 md5_constants<void>::S[round]); 31 } 32 roundh(int round,uint32_t & a,uint32_t & b,uint32_t & c,uint32_t & d,const uint32_t * M)33 static inline void roundh(int round, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, const uint32_t* M) 34 { 35 a = b + rotate_left(a + (b ^ c ^ d) + md5_constants<void>::K[round] + M[(3 * round + 5) % 16], 36 md5_constants<void>::S[round]); 37 } 38 roundi(int round,uint32_t & a,uint32_t & b,uint32_t & c,uint32_t & d,const uint32_t * M)39 static inline void roundi(int round, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d, const uint32_t* M) 40 { 41 a = b + rotate_left(a + (c ^ (b | ~d)) + md5_constants<void>::K[round] + M[(7 * round) % 16], 42 md5_constants<void>::S[round]); 43 } 44 45 } 46 47 class md5_provider 48 { 49 public: 50 static const bool is_xof = false; 51 md5_provider()52 md5_provider() 53 { 54 } 55 ~md5_provider()56 ~md5_provider() 57 { 58 clear(); 59 } 60 init()61 inline void init() 62 { 63 H[0] = 0x67452301; 64 H[1] = 0xefcdab89; 65 H[2] = 0x98badcfe; 66 H[3] = 0x10325476; 67 pos = 0; 68 total = 0; 69 } 70 update(const unsigned char * data,size_t len)71 inline void update(const unsigned char* data, size_t len) 72 { 73 detail::absorb_bytes(data, len, 64, 64, m.data(), pos, total, 74 [this](const unsigned char* data, size_t len) { transform(data, len); }); 75 } 76 final(unsigned char * hash)77 inline void final(unsigned char* hash) 78 { 79 total += pos * 8; 80 m[pos++] = 0x80; 81 if (pos > 56) 82 { 83 if (pos != 64) 84 memset(&m[pos], 0, 64 - pos); 85 transform(&m[0], 1); 86 pos = 0; 87 } 88 memset(&m[0] + pos, 0, 56 - pos); 89 memcpy(&m[0] + (64 - 8), &total, 64 / 8); 90 transform(&m[0], 1); 91 memcpy(hash, H.data(), 16); 92 } 93 clear()94 inline void clear() 95 { 96 zero_memory(H); 97 zero_memory(m); 98 } 99 hash_size() const100 inline size_t hash_size() const { return 128; } 101 102 private: transform(const unsigned char * data,size_t num_blks)103 inline void transform(const unsigned char* data, size_t num_blks) 104 { 105 const uint32_t* M = reinterpret_cast<const uint32_t*>(data); 106 for (uint64_t blk = 0; blk < num_blks; blk++, M += 16) 107 { 108 uint32_t a = H[0]; 109 uint32_t b = H[1]; 110 uint32_t c = H[2]; 111 uint32_t d = H[3]; 112 113 md5_functions::roundf(0, a, b, c, d, M); 114 md5_functions::roundf(1, d, a, b, c, M); 115 md5_functions::roundf(2, c, d, a, b, M); 116 md5_functions::roundf(3, b, c, d, a, M); 117 md5_functions::roundf(4, a, b, c, d, M); 118 md5_functions::roundf(5, d, a, b, c, M); 119 md5_functions::roundf(6, c, d, a, b, M); 120 md5_functions::roundf(7, b, c, d, a, M); 121 md5_functions::roundf(8, a, b, c, d, M); 122 md5_functions::roundf(9, d, a, b, c, M); 123 md5_functions::roundf(10, c, d, a, b, M); 124 md5_functions::roundf(11, b, c, d, a, M); 125 md5_functions::roundf(12, a, b, c, d, M); 126 md5_functions::roundf(13, d, a, b, c, M); 127 md5_functions::roundf(14, c, d, a, b, M); 128 md5_functions::roundf(15, b, c, d, a, M); 129 130 md5_functions::roundg(16, a, b, c, d, M); 131 md5_functions::roundg(17, d, a, b, c, M); 132 md5_functions::roundg(18, c, d, a, b, M); 133 md5_functions::roundg(19, b, c, d, a, M); 134 md5_functions::roundg(20, a, b, c, d, M); 135 md5_functions::roundg(21, d, a, b, c, M); 136 md5_functions::roundg(22, c, d, a, b, M); 137 md5_functions::roundg(23, b, c, d, a, M); 138 md5_functions::roundg(24, a, b, c, d, M); 139 md5_functions::roundg(25, d, a, b, c, M); 140 md5_functions::roundg(26, c, d, a, b, M); 141 md5_functions::roundg(27, b, c, d, a, M); 142 md5_functions::roundg(28, a, b, c, d, M); 143 md5_functions::roundg(29, d, a, b, c, M); 144 md5_functions::roundg(30, c, d, a, b, M); 145 md5_functions::roundg(31, b, c, d, a, M); 146 147 md5_functions::roundh(32, a, b, c, d, M); 148 md5_functions::roundh(33, d, a, b, c, M); 149 md5_functions::roundh(34, c, d, a, b, M); 150 md5_functions::roundh(35, b, c, d, a, M); 151 md5_functions::roundh(36, a, b, c, d, M); 152 md5_functions::roundh(37, d, a, b, c, M); 153 md5_functions::roundh(38, c, d, a, b, M); 154 md5_functions::roundh(39, b, c, d, a, M); 155 md5_functions::roundh(40, a, b, c, d, M); 156 md5_functions::roundh(41, d, a, b, c, M); 157 md5_functions::roundh(42, c, d, a, b, M); 158 md5_functions::roundh(43, b, c, d, a, M); 159 md5_functions::roundh(44, a, b, c, d, M); 160 md5_functions::roundh(45, d, a, b, c, M); 161 md5_functions::roundh(46, c, d, a, b, M); 162 md5_functions::roundh(47, b, c, d, a, M); 163 164 md5_functions::roundi(48, a, b, c, d, M); 165 md5_functions::roundi(49, d, a, b, c, M); 166 md5_functions::roundi(50, c, d, a, b, M); 167 md5_functions::roundi(51, b, c, d, a, M); 168 md5_functions::roundi(52, a, b, c, d, M); 169 md5_functions::roundi(53, d, a, b, c, M); 170 md5_functions::roundi(54, c, d, a, b, M); 171 md5_functions::roundi(55, b, c, d, a, M); 172 md5_functions::roundi(56, a, b, c, d, M); 173 md5_functions::roundi(57, d, a, b, c, M); 174 md5_functions::roundi(58, c, d, a, b, M); 175 md5_functions::roundi(59, b, c, d, a, M); 176 md5_functions::roundi(60, a, b, c, d, M); 177 md5_functions::roundi(61, d, a, b, c, M); 178 md5_functions::roundi(62, c, d, a, b, M); 179 md5_functions::roundi(63, b, c, d, a, M); 180 181 H[0] += a; 182 H[1] += b; 183 H[2] += c; 184 H[3] += d; 185 } 186 } 187 188 std::array<uint32_t, 4> H; 189 std::array<unsigned char, 64> m; 190 size_t pos; 191 uint64_t total; 192 }; 193 194 } // namespace detail 195 196 } // namespace digestpp 197 198 #endif