Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame^] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm |
| 15 | */ |
| 16 | |
| 17 | /* |
| 18 | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All |
| 19 | rights reserved. |
| 20 | |
| 21 | License to copy and use this software is granted provided that it |
| 22 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest |
| 23 | Algorithm" in all material mentioning or referencing this software |
| 24 | or this function. |
| 25 | |
| 26 | License is also granted to make and use derivative works provided |
| 27 | that such works are identified as "derived from the RSA Data |
| 28 | Security, Inc. MD5 Message-Digest Algorithm" in all material |
| 29 | mentioning or referencing the derived work. |
| 30 | |
| 31 | RSA Data Security, Inc. makes no representations concerning either |
| 32 | the merchantability of this software or the suitability of this |
| 33 | software for any particular purpose. It is provided "as is" |
| 34 | without express or implied warranty of any kind. |
| 35 | |
| 36 | These notices must be retained in any copies of any part of this |
| 37 | documentation and/or software. |
| 38 | */ |
| 39 | |
Han-Wen Nienhuys | 36fbe63 | 2015-04-21 13:58:08 +0000 | [diff] [blame] | 40 | #include "src/main/cpp/util/md5.h" |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 41 | |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 42 | #include <stdint.h> |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 43 | #include <string.h> // for memcpy |
| 44 | #include <stddef.h> // for ofsetof |
| 45 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 46 | #if !_STRING_ARCH_unaligned |
| 47 | # ifdef _LP64 |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 48 | # define UNALIGNED_P(p) (reinterpret_cast<uint64_t>(p) % \ |
| 49 | __alignof__(uint32_t) != 0) // NOLINT |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 50 | # else |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 51 | # define UNALIGNED_P(p) (reinterpret_cast<uint32_t>(p) % \ |
| 52 | __alignof__(uint32_t) != 0) // NOLINT |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 53 | # endif |
| 54 | #else |
| 55 | # define UNALIGNED_P(p) (0) |
| 56 | #endif |
| 57 | |
| 58 | namespace blaze_util { |
| 59 | |
| 60 | static const unsigned int k8Bytes = 64; |
| 61 | static const unsigned int k8ByteMask = 63; |
| 62 | |
| 63 | static const unsigned char kPadding[64] = { |
| 64 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 65 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 66 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 67 | }; |
| 68 | |
| 69 | // Digit conversion. |
| 70 | static char hex_char[] = "0123456789abcdef"; |
| 71 | |
| 72 | // This is a templated function so that T can be either a char* |
| 73 | // or a string. This works because we use the [] operator to access |
| 74 | // individual characters at a time. |
| 75 | template <typename T> |
| 76 | static void b2a_hex_t(const unsigned char* b, T a, int num) { |
| 77 | for (int i = 0; i < num; i++) { |
| 78 | a[i * 2 + 0] = hex_char[b[i] >> 4]; |
| 79 | a[i * 2 + 1] = hex_char[b[i] & 0xf]; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | // ---------------------------------------------------------------------- |
| 84 | // b2a_hex() |
| 85 | // Description: Binary-to-Ascii hex conversion. This converts |
| 86 | // 'num' bytes of binary to a 2*'num'-character hexadecimal representation |
| 87 | // Return value: 2*'num' characters of ascii text (via the 'to' argument) |
| 88 | // ---------------------------------------------------------------------- |
| 89 | static void b2a_hex(const unsigned char* from, string* to, int num) { |
| 90 | to->resize(num << 1); |
| 91 | b2a_hex_t<string&>(from, *to, num); |
| 92 | } |
| 93 | |
| 94 | Md5Digest::Md5Digest() { |
| 95 | Reset(); |
| 96 | } |
| 97 | |
| 98 | Md5Digest::Md5Digest(const Md5Digest& original) { |
| 99 | memcpy(state, original.state, sizeof(original.state)); |
| 100 | memcpy(count, original.count, sizeof(original.count)); |
| 101 | memcpy(ctx_buffer, original.ctx_buffer, original.ctx_buffer_len); |
| 102 | ctx_buffer_len = original.ctx_buffer_len; |
| 103 | } |
| 104 | |
| 105 | void Md5Digest::Reset() { |
| 106 | count[0] = count[1] = 0; |
| 107 | ctx_buffer_len = 0; |
| 108 | // Load magic initialization constants. |
| 109 | state[0] = 0x67452301; |
| 110 | state[1] = 0xefcdab89; |
| 111 | state[2] = 0x98badcfe; |
| 112 | state[3] = 0x10325476; |
| 113 | } |
| 114 | |
| 115 | void Md5Digest::Update(const void *buf, unsigned int length) { |
| 116 | const unsigned char *input = reinterpret_cast<const unsigned char*>(buf); |
| 117 | unsigned int buffer_space_len; |
| 118 | |
| 119 | buffer_space_len = k8Bytes - ctx_buffer_len; |
| 120 | |
| 121 | // Transform as many times as possible. |
| 122 | if (length >= buffer_space_len) { |
| 123 | if (buffer_space_len != 0 && ctx_buffer_len != 0) { |
| 124 | // Copy more bytes to fill the complete buffer |
| 125 | memcpy(ctx_buffer + ctx_buffer_len, input, buffer_space_len); |
| 126 | Transform(ctx_buffer, k8Bytes); |
| 127 | input += buffer_space_len; |
| 128 | length -= buffer_space_len; |
| 129 | ctx_buffer_len = 0; |
| 130 | } |
| 131 | |
| 132 | if (UNALIGNED_P(input)) { |
| 133 | while (length >= k8Bytes) { |
| 134 | memcpy(ctx_buffer, input, k8Bytes); |
| 135 | Transform(ctx_buffer, k8Bytes); |
| 136 | input += k8Bytes; |
| 137 | length -= k8Bytes; |
| 138 | } |
| 139 | } else if (length >= k8Bytes) { |
| 140 | Transform(input, length & ~k8ByteMask); |
| 141 | input += length & ~k8ByteMask; |
| 142 | length &= k8ByteMask; |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | // Buffer remaining input |
| 147 | memcpy(ctx_buffer + ctx_buffer_len, input, length); |
| 148 | ctx_buffer_len += length; |
| 149 | } |
| 150 | |
| 151 | void Md5Digest::Finish(unsigned char digest[16]) { |
| 152 | count[0] += ctx_buffer_len; |
| 153 | if (count[0] < ctx_buffer_len) { |
| 154 | ++count[1]; |
| 155 | } |
| 156 | |
| 157 | /* Put the 64-bit file length in *bits* at the end of the buffer. */ |
| 158 | unsigned int size = (ctx_buffer_len < 56 ? 64 : 128); |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 159 | *(reinterpret_cast<uint32_t*>(ctx_buffer + size - 8)) = count[0] << 3; |
| 160 | *(reinterpret_cast<uint32_t*>(ctx_buffer + size - 4)) = |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 161 | (count[1] << 3) | (count[0] >> 29); |
| 162 | |
| 163 | memcpy(ctx_buffer + ctx_buffer_len, kPadding, size - 8 - ctx_buffer_len); |
| 164 | |
| 165 | Transform(ctx_buffer, size); |
| 166 | |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 167 | uint32_t* r = reinterpret_cast<uint32_t*>(digest); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 168 | r[0] = state[0]; |
| 169 | r[1] = state[1]; |
| 170 | r[2] = state[2]; |
| 171 | r[3] = state[3]; |
| 172 | } |
| 173 | |
| 174 | void Md5Digest::Transform( |
| 175 | const unsigned char* buffer, unsigned int len) { |
| 176 | // Constants for transform routine. |
| 177 | #define S11 7 |
| 178 | #define S12 12 |
| 179 | #define S13 17 |
| 180 | #define S14 22 |
| 181 | #define S21 5 |
| 182 | #define S22 9 |
| 183 | #define S23 14 |
| 184 | #define S24 20 |
| 185 | #define S31 4 |
| 186 | #define S32 11 |
| 187 | #define S33 16 |
| 188 | #define S34 23 |
| 189 | #define S41 6 |
| 190 | #define S42 10 |
| 191 | #define S43 15 |
| 192 | #define S44 21 |
| 193 | |
| 194 | // F, G, H and I are basic MD5 functions. |
| 195 | /* These are the four functions used in the four steps of the MD5 algorithm |
| 196 | and defined in the RFC 1321. The first function is a little bit optimized |
| 197 | (as found in Colin Plumbs public domain implementation). */ |
| 198 | /* #define F(b, c, d) ((b & c) | (~b & d)) */ |
| 199 | #define F(x, y, z) (z ^ (x & (y ^ z))) |
| 200 | #define G(x, y, z) F (z, x, y) |
| 201 | #define H(x, y, z) ((x) ^ (y) ^ (z)) |
| 202 | #define I(x, y, z) ((y) ^ ((x) | (~z))) |
| 203 | |
| 204 | // ROTATE_LEFT rotates x left n bits. |
| 205 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) |
| 206 | |
| 207 | // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. |
| 208 | // Rotation is separate from addition to prevent recomputation. |
| 209 | #define FF(a, b, c, d, s, ac) { \ |
| 210 | (a) += F((b), (c), (d)) + ((*x_pos++ = *cur_word++)) + \ |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 211 | static_cast<uint32_t>(ac); \ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 212 | (a) = ROTATE_LEFT((a), (s)); \ |
| 213 | (a) += (b); \ |
| 214 | } |
| 215 | |
| 216 | #define GG(a, b, c, d, x, s, ac) { \ |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 217 | (a) += G((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 218 | (a) = ROTATE_LEFT((a), (s)); \ |
| 219 | (a) += (b); \ |
| 220 | } |
| 221 | #define HH(a, b, c, d, x, s, ac) { \ |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 222 | (a) += H((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 223 | (a) = ROTATE_LEFT((a), (s)); \ |
| 224 | (a) += (b); \ |
| 225 | } |
| 226 | #define II(a, b, c, d, x, s, ac) { \ |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 227 | (a) += I((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 228 | (a) = ROTATE_LEFT((a), (s)); \ |
| 229 | (a) += (b); \ |
| 230 | } |
| 231 | |
| 232 | count[0] += len; |
| 233 | if (count[0] < len) { |
| 234 | ++count[1]; |
| 235 | } |
| 236 | |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 237 | uint32_t a = state[0]; |
| 238 | uint32_t b = state[1]; |
| 239 | uint32_t c = state[2]; |
| 240 | uint32_t d = state[3]; |
| 241 | uint32_t x[16]; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 242 | |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 243 | const uint32_t *cur_word = reinterpret_cast<const uint32_t*>(buffer); |
| 244 | const uint32_t *end_word = cur_word + (len / sizeof(uint32_t)); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 245 | |
| 246 | while (cur_word < end_word) { |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 247 | uint32_t *x_pos = x; |
| 248 | uint32_t prev_a = a; |
| 249 | uint32_t prev_b = b; |
| 250 | uint32_t prev_c = c; |
| 251 | uint32_t prev_d = d; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 252 | |
| 253 | // Round 1 |
| 254 | FF(a, b, c, d, S11, 0xd76aa478); // 1 |
| 255 | FF(d, a, b, c, S12, 0xe8c7b756); // 2 |
| 256 | FF(c, d, a, b, S13, 0x242070db); // 3 |
| 257 | FF(b, c, d, a, S14, 0xc1bdceee); // 4 |
| 258 | FF(a, b, c, d, S11, 0xf57c0faf); // 5 |
| 259 | FF(d, a, b, c, S12, 0x4787c62a); // 6 |
| 260 | FF(c, d, a, b, S13, 0xa8304613); // 7 |
| 261 | FF(b, c, d, a, S14, 0xfd469501); // 8 |
| 262 | FF(a, b, c, d, S11, 0x698098d8); // 9 |
| 263 | FF(d, a, b, c, S12, 0x8b44f7af); // 10 |
| 264 | FF(c, d, a, b, S13, 0xffff5bb1); // 11 |
| 265 | FF(b, c, d, a, S14, 0x895cd7be); // 12 |
| 266 | FF(a, b, c, d, S11, 0x6b901122); // 13 |
| 267 | FF(d, a, b, c, S12, 0xfd987193); // 14 |
| 268 | FF(c, d, a, b, S13, 0xa679438e); // 15 |
| 269 | FF(b, c, d, a, S14, 0x49b40821); // 16 |
| 270 | |
| 271 | // Round 2 |
| 272 | GG(a, b, c, d, x[ 1], S21, 0xf61e2562); // 17 |
| 273 | GG(d, a, b, c, x[ 6], S22, 0xc040b340); // 18 |
| 274 | GG(c, d, a, b, x[11], S23, 0x265e5a51); // 19 |
| 275 | GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); // 20 |
| 276 | GG(a, b, c, d, x[ 5], S21, 0xd62f105d); // 21 |
| 277 | GG(d, a, b, c, x[10], S22, 0x2441453); // 22 |
| 278 | GG(c, d, a, b, x[15], S23, 0xd8a1e681); // 23 |
| 279 | GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); // 24 |
| 280 | GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); // 25 |
| 281 | GG(d, a, b, c, x[14], S22, 0xc33707d6); // 26 |
| 282 | GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); // 27 |
| 283 | GG(b, c, d, a, x[ 8], S24, 0x455a14ed); // 28 |
| 284 | GG(a, b, c, d, x[13], S21, 0xa9e3e905); // 29 |
| 285 | GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); // 30 |
| 286 | GG(c, d, a, b, x[ 7], S23, 0x676f02d9); // 31 |
| 287 | GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32 |
| 288 | |
| 289 | // Round 3 |
| 290 | HH(a, b, c, d, x[ 5], S31, 0xfffa3942); // 33 |
| 291 | HH(d, a, b, c, x[ 8], S32, 0x8771f681); // 34 |
| 292 | HH(c, d, a, b, x[11], S33, 0x6d9d6122); // 35 |
| 293 | HH(b, c, d, a, x[14], S34, 0xfde5380c); // 36 |
| 294 | HH(a, b, c, d, x[ 1], S31, 0xa4beea44); // 37 |
| 295 | HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); // 38 |
| 296 | HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); // 39 |
| 297 | HH(b, c, d, a, x[10], S34, 0xbebfbc70); // 40 |
| 298 | HH(a, b, c, d, x[13], S31, 0x289b7ec6); // 41 |
| 299 | HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); // 42 |
| 300 | HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); // 43 |
| 301 | HH(b, c, d, a, x[ 6], S34, 0x4881d05); // 44 |
| 302 | HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); // 45 |
| 303 | HH(d, a, b, c, x[12], S32, 0xe6db99e5); // 46 |
| 304 | HH(c, d, a, b, x[15], S33, 0x1fa27cf8); // 47 |
| 305 | HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); // 48 |
| 306 | |
| 307 | // Round 4 |
| 308 | II(a, b, c, d, x[ 0], S41, 0xf4292244); // 49 |
| 309 | II(d, a, b, c, x[ 7], S42, 0x432aff97); // 50 |
| 310 | II(c, d, a, b, x[14], S43, 0xab9423a7); // 51 |
| 311 | II(b, c, d, a, x[ 5], S44, 0xfc93a039); // 52 |
| 312 | II(a, b, c, d, x[12], S41, 0x655b59c3); // 53 |
| 313 | II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); // 54 |
| 314 | II(c, d, a, b, x[10], S43, 0xffeff47d); // 55 |
| 315 | II(b, c, d, a, x[ 1], S44, 0x85845dd1); // 56 |
| 316 | II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); // 57 |
| 317 | II(d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58 |
| 318 | II(c, d, a, b, x[ 6], S43, 0xa3014314); // 59 |
| 319 | II(b, c, d, a, x[13], S44, 0x4e0811a1); // 60 |
| 320 | II(a, b, c, d, x[ 4], S41, 0xf7537e82); // 61 |
| 321 | II(d, a, b, c, x[11], S42, 0xbd3af235); // 62 |
| 322 | II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); // 63 |
| 323 | II(b, c, d, a, x[ 9], S44, 0xeb86d391); // 64 |
| 324 | |
| 325 | a += prev_a; |
| 326 | b += prev_b; |
| 327 | c += prev_c; |
| 328 | d += prev_d; |
| 329 | } |
| 330 | |
| 331 | state[0] = a; |
| 332 | state[1] = b; |
| 333 | state[2] = c; |
| 334 | state[3] = d; |
| 335 | } |
| 336 | |
| 337 | string Md5Digest::String() const { |
| 338 | string result; |
Thiago Farina | 8a67da4 | 2015-05-05 18:04:50 +0000 | [diff] [blame] | 339 | b2a_hex(reinterpret_cast<const uint8_t*>(state), &result, 16); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 340 | return result; |
| 341 | } |
| 342 | |
| 343 | } // namespace blaze_util |