blob: 05d2ba276c4b9014d5b0977c3b470724e4331d36 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
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 Nienhuys36fbe632015-04-21 13:58:08 +000040#include "src/main/cpp/util/md5.h"
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010041
Thiago Farina8a67da42015-05-05 18:04:50 +000042#include <stdint.h>
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043#include <string.h> // for memcpy
44#include <stddef.h> // for ofsetof
45
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046#if !_STRING_ARCH_unaligned
47# ifdef _LP64
Thiago Farina8a67da42015-05-05 18:04:50 +000048# define UNALIGNED_P(p) (reinterpret_cast<uint64_t>(p) % \
49 __alignof__(uint32_t) != 0) // NOLINT
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010050# else
Thiago Farina8a67da42015-05-05 18:04:50 +000051# define UNALIGNED_P(p) (reinterpret_cast<uint32_t>(p) % \
52 __alignof__(uint32_t) != 0) // NOLINT
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053# endif
54#else
55# define UNALIGNED_P(p) (0)
56#endif
57
58namespace blaze_util {
59
60static const unsigned int k8Bytes = 64;
61static const unsigned int k8ByteMask = 63;
62
63static 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.
70static 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.
75template <typename T>
76static 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// ----------------------------------------------------------------------
89static 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
94Md5Digest::Md5Digest() {
95 Reset();
96}
97
98Md5Digest::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
105void 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
115void 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
151void 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 Farina8a67da42015-05-05 18:04:50 +0000159 *(reinterpret_cast<uint32_t*>(ctx_buffer + size - 8)) = count[0] << 3;
160 *(reinterpret_cast<uint32_t*>(ctx_buffer + size - 4)) =
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100161 (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 Farina8a67da42015-05-05 18:04:50 +0000167 uint32_t* r = reinterpret_cast<uint32_t*>(digest);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100168 r[0] = state[0];
169 r[1] = state[1];
170 r[2] = state[2];
171 r[3] = state[3];
172}
173
174void 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 Farina8a67da42015-05-05 18:04:50 +0000211 static_cast<uint32_t>(ac); \
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100212 (a) = ROTATE_LEFT((a), (s)); \
213 (a) += (b); \
214 }
215
216#define GG(a, b, c, d, x, s, ac) { \
Thiago Farina8a67da42015-05-05 18:04:50 +0000217 (a) += G((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100218 (a) = ROTATE_LEFT((a), (s)); \
219 (a) += (b); \
220 }
221#define HH(a, b, c, d, x, s, ac) { \
Thiago Farina8a67da42015-05-05 18:04:50 +0000222 (a) += H((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100223 (a) = ROTATE_LEFT((a), (s)); \
224 (a) += (b); \
225 }
226#define II(a, b, c, d, x, s, ac) { \
Thiago Farina8a67da42015-05-05 18:04:50 +0000227 (a) += I((b), (c), (d)) + (x) + static_cast<uint32_t>(ac); \
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100228 (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 Farina8a67da42015-05-05 18:04:50 +0000237 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 Nienhuysd08b27f2015-02-25 16:45:20 +0100242
Thiago Farina8a67da42015-05-05 18:04:50 +0000243 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 Nienhuysd08b27f2015-02-25 16:45:20 +0100245
246 while (cur_word < end_word) {
Thiago Farina8a67da42015-05-05 18:04:50 +0000247 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 Nienhuysd08b27f2015-02-25 16:45:20 +0100252
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
337string Md5Digest::String() const {
338 string result;
Thiago Farina8a67da42015-05-05 18:04:50 +0000339 b2a_hex(reinterpret_cast<const uint8_t*>(state), &result, 16);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100340 return result;
341}
342
343} // namespace blaze_util