|  | // Copyright 2014 The Bazel Authors. All rights reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  | /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm | 
|  | */ | 
|  |  | 
|  | /* | 
|  | Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All | 
|  | rights reserved. | 
|  |  | 
|  | License to copy and use this software is granted provided that it | 
|  | is identified as the "RSA Data Security, Inc. MD5 Message-Digest | 
|  | Algorithm" in all material mentioning or referencing this software | 
|  | or this function. | 
|  |  | 
|  | License is also granted to make and use derivative works provided | 
|  | that such works are identified as "derived from the RSA Data | 
|  | Security, Inc. MD5 Message-Digest Algorithm" in all material | 
|  | mentioning or referencing the derived work. | 
|  |  | 
|  | RSA Data Security, Inc. makes no representations concerning either | 
|  | the merchantability of this software or the suitability of this | 
|  | software for any particular purpose. It is provided "as is" | 
|  | without express or implied warranty of any kind. | 
|  |  | 
|  | These notices must be retained in any copies of any part of this | 
|  | documentation and/or software. | 
|  | */ | 
|  |  | 
|  | #include "src/main/cpp/util/md5.h" | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #if !_STRING_ARCH_unaligned | 
|  | #if defined(_LP64) || defined(_WIN64) | 
|  | #  define UNALIGNED_P(p) (reinterpret_cast<uint64_t>(p) % \ | 
|  | __alignof__(uint32_t) != 0)  // NOLINT | 
|  | # else | 
|  | #  define UNALIGNED_P(p) (reinterpret_cast<uint32_t>(p) % \ | 
|  | __alignof__(uint32_t) != 0)  // NOLINT | 
|  | # endif | 
|  | #else | 
|  | #  define UNALIGNED_P(p) (0) | 
|  | #endif | 
|  |  | 
|  | namespace blaze_util { | 
|  |  | 
|  | using std::string; | 
|  |  | 
|  | static const unsigned int k8Bytes = 64; | 
|  | static const unsigned int k8ByteMask = 63; | 
|  |  | 
|  | static const unsigned char kPadding[64] = { | 
|  | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 
|  | }; | 
|  |  | 
|  | // Digit conversion. | 
|  | static char hex_char[] = "0123456789abcdef"; | 
|  |  | 
|  | // This is a templated function so that T can be either a char* | 
|  | // or a string.  This works because we use the [] operator to access | 
|  | // individual characters at a time. | 
|  | template <typename T> | 
|  | static void b2a_hex_t(const unsigned char* b, T a, int num) { | 
|  | for (int i = 0; i < num; i++) { | 
|  | a[i * 2 + 0] = hex_char[b[i] >> 4]; | 
|  | a[i * 2 + 1] = hex_char[b[i] & 0xf]; | 
|  | } | 
|  | } | 
|  |  | 
|  | // ---------------------------------------------------------------------- | 
|  | // b2a_hex() | 
|  | //  Description: Binary-to-Ascii hex conversion.  This converts | 
|  | //   'num' bytes of binary to a 2*'num'-character hexadecimal representation | 
|  | //    Return value: 2*'num' characters of ascii text (via the 'to' argument) | 
|  | // ---------------------------------------------------------------------- | 
|  | static void b2a_hex(const unsigned char* from, string* to, int num) { | 
|  | to->resize(num << 1); | 
|  | b2a_hex_t<string&>(from, *to, num); | 
|  | } | 
|  |  | 
|  | Md5Digest::Md5Digest() { | 
|  | Reset(); | 
|  | } | 
|  |  | 
|  | Md5Digest::Md5Digest(const Md5Digest& original) { | 
|  | memcpy(state, original.state, sizeof(original.state)); | 
|  | memcpy(count, original.count, sizeof(original.count)); | 
|  | memcpy(ctx_buffer, original.ctx_buffer, original.ctx_buffer_len); | 
|  | ctx_buffer_len = original.ctx_buffer_len; | 
|  | } | 
|  |  | 
|  | void Md5Digest::Reset() { | 
|  | count[0] = count[1] = 0; | 
|  | ctx_buffer_len = 0; | 
|  | // Load magic initialization constants. | 
|  | state[0] = 0x67452301; | 
|  | state[1] = 0xefcdab89; | 
|  | state[2] = 0x98badcfe; | 
|  | state[3] = 0x10325476; | 
|  | } | 
|  |  | 
|  | void Md5Digest::Update(const void *buf, unsigned int length) { | 
|  | const unsigned char *input = reinterpret_cast<const unsigned char*>(buf); | 
|  | unsigned int buffer_space_len; | 
|  |  | 
|  | buffer_space_len = k8Bytes - ctx_buffer_len; | 
|  |  | 
|  | // Transform as many times as possible. | 
|  | if (length >= buffer_space_len) { | 
|  | if (buffer_space_len != 0 && ctx_buffer_len != 0) { | 
|  | // Copy more bytes to fill the complete buffer | 
|  | memcpy(ctx_buffer + ctx_buffer_len, input, buffer_space_len); | 
|  | Transform(ctx_buffer, k8Bytes); | 
|  | input += buffer_space_len; | 
|  | length -= buffer_space_len; | 
|  | ctx_buffer_len = 0; | 
|  | } | 
|  |  | 
|  | if (UNALIGNED_P(input)) { | 
|  | while (length >= k8Bytes) { | 
|  | memcpy(ctx_buffer, input, k8Bytes); | 
|  | Transform(ctx_buffer, k8Bytes); | 
|  | input += k8Bytes; | 
|  | length -= k8Bytes; | 
|  | } | 
|  | } else if (length >= k8Bytes) { | 
|  | Transform(input, length & ~k8ByteMask); | 
|  | input += length & ~k8ByteMask; | 
|  | length &= k8ByteMask; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Buffer remaining input | 
|  | memcpy(ctx_buffer + ctx_buffer_len, input, length); | 
|  | ctx_buffer_len += length; | 
|  | } | 
|  |  | 
|  | void Md5Digest::Finish(unsigned char digest[16]) { | 
|  | count[0] += ctx_buffer_len; | 
|  | if (count[0] < ctx_buffer_len) { | 
|  | ++count[1]; | 
|  | } | 
|  |  | 
|  | /* Put the 64-bit file length in *bits* at the end of the buffer.  */ | 
|  | unsigned int size = (ctx_buffer_len < 56 ? 64 : 128); | 
|  | uint32_t words[2] = { htole32(count[0] << 3), | 
|  | htole32((count[1] << 3) | (count[0] >> 29)) }; | 
|  | memcpy(ctx_buffer + size - 8, words, 8); | 
|  |  | 
|  | memcpy(ctx_buffer + ctx_buffer_len, kPadding, size - 8 - ctx_buffer_len); | 
|  |  | 
|  | Transform(ctx_buffer, size); | 
|  |  | 
|  | uint32_t* r = reinterpret_cast<uint32_t*>(digest); | 
|  | r[0] = state[0]; | 
|  | r[1] = state[1]; | 
|  | r[2] = state[2]; | 
|  | r[3] = state[3]; | 
|  | } | 
|  |  | 
|  | void Md5Digest::Transform( | 
|  | const unsigned char* buffer, unsigned int len) { | 
|  | // Constants for transform routine. | 
|  | #define S11 7 | 
|  | #define S12 12 | 
|  | #define S13 17 | 
|  | #define S14 22 | 
|  | #define S21 5 | 
|  | #define S22 9 | 
|  | #define S23 14 | 
|  | #define S24 20 | 
|  | #define S31 4 | 
|  | #define S32 11 | 
|  | #define S33 16 | 
|  | #define S34 23 | 
|  | #define S41 6 | 
|  | #define S42 10 | 
|  | #define S43 15 | 
|  | #define S44 21 | 
|  |  | 
|  | // F, G, H and I are basic MD5 functions. | 
|  | /* These are the four functions used in the four steps of the MD5 algorithm | 
|  | and defined in the RFC 1321.  The first function is a little bit optimized | 
|  | (as found in Colin Plumbs public domain implementation).  */ | 
|  | /* #define F(b, c, d) ((b & c) | (~b & d)) */ | 
|  | #define F(x, y, z) (z ^ (x & (y ^ z))) | 
|  | #define G(x, y, z) F (z, x, y) | 
|  | #define H(x, y, z) ((x) ^ (y) ^ (z)) | 
|  | #define I(x, y, z) ((y) ^ ((x) | (~z))) | 
|  |  | 
|  | // ROTATE_LEFT rotates x left n bits. | 
|  | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) | 
|  |  | 
|  | // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. | 
|  | // Rotation is separate from addition to prevent recomputation. | 
|  | // Note: The behavior we want is really LE to host, but host to le is the | 
|  | // same thing. | 
|  | #define FF(a, b, c, d, s, ac) { \ | 
|  | (a) += F((b), (c), (d)) + ((*x_pos++ = htole32(*cur_word))) + \ | 
|  | static_cast<uint32_t>(ac); \ | 
|  | (a) = ROTATE_LEFT((a), (s)); \ | 
|  | (a) += (b); \ | 
|  | cur_word++; \ | 
|  | } | 
|  |  | 
|  | #define GG(a, b, c, d, x, s, ac) { \ | 
|  | (a) += G((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \ | 
|  | (a) = ROTATE_LEFT((a), (s)); \ | 
|  | (a) += (b); \ | 
|  | } | 
|  | #define HH(a, b, c, d, x, s, ac) { \ | 
|  | (a) += H((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \ | 
|  | (a) = ROTATE_LEFT((a), (s)); \ | 
|  | (a) += (b); \ | 
|  | } | 
|  | #define II(a, b, c, d, x, s, ac) { \ | 
|  | (a) += I((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \ | 
|  | (a) = ROTATE_LEFT((a), (s)); \ | 
|  | (a) += (b); \ | 
|  | } | 
|  |  | 
|  | count[0] += len; | 
|  | if (count[0] < len) { | 
|  | ++count[1]; | 
|  | } | 
|  |  | 
|  | uint32_t a = state[0]; | 
|  | uint32_t b = state[1]; | 
|  | uint32_t c = state[2]; | 
|  | uint32_t d = state[3]; | 
|  | uint32_t x[16]; | 
|  |  | 
|  | const uint32_t *cur_word = reinterpret_cast<const uint32_t*>(buffer); | 
|  | const uint32_t *end_word = cur_word + (len / sizeof(uint32_t)); | 
|  |  | 
|  | while (cur_word < end_word) { | 
|  | uint32_t *x_pos = x; | 
|  | uint32_t prev_a = a; | 
|  | uint32_t prev_b = b; | 
|  | uint32_t prev_c = c; | 
|  | uint32_t prev_d = d; | 
|  |  | 
|  | // Round 1 | 
|  | FF(a, b, c, d, S11, 0xd76aa478);  // 1 | 
|  | FF(d, a, b, c, S12, 0xe8c7b756);  // 2 | 
|  | FF(c, d, a, b, S13, 0x242070db);  // 3 | 
|  | FF(b, c, d, a, S14, 0xc1bdceee);  // 4 | 
|  | FF(a, b, c, d, S11, 0xf57c0faf);  // 5 | 
|  | FF(d, a, b, c, S12, 0x4787c62a);  // 6 | 
|  | FF(c, d, a, b, S13, 0xa8304613);  // 7 | 
|  | FF(b, c, d, a, S14, 0xfd469501);  // 8 | 
|  | FF(a, b, c, d, S11, 0x698098d8);  // 9 | 
|  | FF(d, a, b, c, S12, 0x8b44f7af);  // 10 | 
|  | FF(c, d, a, b, S13, 0xffff5bb1);  // 11 | 
|  | FF(b, c, d, a, S14, 0x895cd7be);  // 12 | 
|  | FF(a, b, c, d, S11, 0x6b901122);  // 13 | 
|  | FF(d, a, b, c, S12, 0xfd987193);  // 14 | 
|  | FF(c, d, a, b, S13, 0xa679438e);  // 15 | 
|  | FF(b, c, d, a, S14, 0x49b40821);  // 16 | 
|  |  | 
|  | // Round 2 | 
|  | GG(a, b, c, d, x[ 1], S21, 0xf61e2562);  // 17 | 
|  | GG(d, a, b, c, x[ 6], S22, 0xc040b340);  // 18 | 
|  | GG(c, d, a, b, x[11], S23, 0x265e5a51);  // 19 | 
|  | GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa);  // 20 | 
|  | GG(a, b, c, d, x[ 5], S21, 0xd62f105d);  // 21 | 
|  | GG(d, a, b, c, x[10], S22,  0x2441453);  // 22 | 
|  | GG(c, d, a, b, x[15], S23, 0xd8a1e681);  // 23 | 
|  | GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8);  // 24 | 
|  | GG(a, b, c, d, x[ 9], S21, 0x21e1cde6);  // 25 | 
|  | GG(d, a, b, c, x[14], S22, 0xc33707d6);  // 26 | 
|  | GG(c, d, a, b, x[ 3], S23, 0xf4d50d87);  // 27 | 
|  | GG(b, c, d, a, x[ 8], S24, 0x455a14ed);  // 28 | 
|  | GG(a, b, c, d, x[13], S21, 0xa9e3e905);  // 29 | 
|  | GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8);  // 30 | 
|  | GG(c, d, a, b, x[ 7], S23, 0x676f02d9);  // 31 | 
|  | GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);  // 32 | 
|  |  | 
|  | // Round 3 | 
|  | HH(a, b, c, d, x[ 5], S31, 0xfffa3942);  // 33 | 
|  | HH(d, a, b, c, x[ 8], S32, 0x8771f681);  // 34 | 
|  | HH(c, d, a, b, x[11], S33, 0x6d9d6122);  // 35 | 
|  | HH(b, c, d, a, x[14], S34, 0xfde5380c);  // 36 | 
|  | HH(a, b, c, d, x[ 1], S31, 0xa4beea44);  // 37 | 
|  | HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9);  // 38 | 
|  | HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60);  // 39 | 
|  | HH(b, c, d, a, x[10], S34, 0xbebfbc70);  // 40 | 
|  | HH(a, b, c, d, x[13], S31, 0x289b7ec6);  // 41 | 
|  | HH(d, a, b, c, x[ 0], S32, 0xeaa127fa);  // 42 | 
|  | HH(c, d, a, b, x[ 3], S33, 0xd4ef3085);  // 43 | 
|  | HH(b, c, d, a, x[ 6], S34,  0x4881d05);  // 44 | 
|  | HH(a, b, c, d, x[ 9], S31, 0xd9d4d039);  // 45 | 
|  | HH(d, a, b, c, x[12], S32, 0xe6db99e5);  // 46 | 
|  | HH(c, d, a, b, x[15], S33, 0x1fa27cf8);  // 47 | 
|  | HH(b, c, d, a, x[ 2], S34, 0xc4ac5665);  // 48 | 
|  |  | 
|  | // Round 4 | 
|  | II(a, b, c, d, x[ 0], S41, 0xf4292244);  // 49 | 
|  | II(d, a, b, c, x[ 7], S42, 0x432aff97);  // 50 | 
|  | II(c, d, a, b, x[14], S43, 0xab9423a7);  // 51 | 
|  | II(b, c, d, a, x[ 5], S44, 0xfc93a039);  // 52 | 
|  | II(a, b, c, d, x[12], S41, 0x655b59c3);  // 53 | 
|  | II(d, a, b, c, x[ 3], S42, 0x8f0ccc92);  // 54 | 
|  | II(c, d, a, b, x[10], S43, 0xffeff47d);  // 55 | 
|  | II(b, c, d, a, x[ 1], S44, 0x85845dd1);  // 56 | 
|  | II(a, b, c, d, x[ 8], S41, 0x6fa87e4f);  // 57 | 
|  | II(d, a, b, c, x[15], S42, 0xfe2ce6e0);  // 58 | 
|  | II(c, d, a, b, x[ 6], S43, 0xa3014314);  // 59 | 
|  | II(b, c, d, a, x[13], S44, 0x4e0811a1);  // 60 | 
|  | II(a, b, c, d, x[ 4], S41, 0xf7537e82);  // 61 | 
|  | II(d, a, b, c, x[11], S42, 0xbd3af235);  // 62 | 
|  | II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb);  // 63 | 
|  | II(b, c, d, a, x[ 9], S44, 0xeb86d391);  // 64 | 
|  |  | 
|  | a += prev_a; | 
|  | b += prev_b; | 
|  | c += prev_c; | 
|  | d += prev_d; | 
|  | } | 
|  |  | 
|  | state[0] = a; | 
|  | state[1] = b; | 
|  | state[2] = c; | 
|  | state[3] = d; | 
|  | } | 
|  |  | 
|  | string Md5Digest::String() const { | 
|  | string result; | 
|  | unsigned int state_le[4]; | 
|  | // Make sure state_le[4] is in little-endian format. | 
|  | for (int i = 0; i < 4; i++) { | 
|  | state_le[i] = htole32(state[i]); | 
|  | } | 
|  | b2a_hex(reinterpret_cast<const uint8_t*>(state_le), &result, 16); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | }  // namespace blaze_util |