more cleanup
[awesomized/libmemcached] / src / libhashkit / md5.cc
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #include "libhashkit/common.h"
17
18 #include <cstring>
19 #include <sys/types.h>
20
21 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
22
23 #if GCC_VERSION > 40600
24 # pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
25 #endif
26
27 /* POINTER defines a generic pointer type */
28 typedef unsigned char *POINTER;
29 typedef const unsigned char *CONST_POINTER;
30
31 /* UINT4 defines a four byte word */
32 typedef unsigned int UINT4;
33
34 /* MD5 context. */
35 typedef struct {
36 UINT4 state[4]; /* state (ABCD) */
37 UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
38 unsigned char buffer[64]; /* input buffer */
39 } MD5_CTX;
40
41 static void MD5Init(MD5_CTX *context); /* context */
42 static void MD5Update(MD5_CTX *context, /* context */
43 const unsigned char *input, /* input block */
44 unsigned int inputLen); /* length of input block */
45 static void MD5Final(unsigned char digest[16], /* message digest */
46 MD5_CTX *context); /* context */
47
48 /* Constants for MD5Transform routine. */
49
50 #define S11 7
51 #define S12 12
52 #define S13 17
53 #define S14 22
54 #define S21 5
55 #define S22 9
56 #define S23 14
57 #define S24 20
58 #define S31 4
59 #define S32 11
60 #define S33 16
61 #define S34 23
62 #define S41 6
63 #define S42 10
64 #define S43 15
65 #define S44 21
66
67 static void MD5Transform(UINT4 state[4], const unsigned char block[64]);
68 static void Encode(unsigned char *output, UINT4 *input, unsigned int len);
69 static void Decode(UINT4 *output, const unsigned char *input, unsigned int len);
70
71 static unsigned char PADDING[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
75
76 /* F, G, H and I are basic MD5 functions.
77 */
78 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
79 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
80 #define H(x, y, z) ((x) ^ (y) ^ (z))
81 #define I(x, y, z) ((y) ^ ((x) | (~z)))
82
83 /* ROTATE_LEFT rotates x left n bits.
84 */
85 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
86
87 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
88 Rotation is separate from addition to prevent recomputation.
89 */
90 #define FF(a, b, c, d, x, s, ac) \
91 { \
92 (a) += F((b), (c), (d)) + (x) + (UINT4)(ac); \
93 (a) = ROTATE_LEFT((a), (s)); \
94 (a) += (b); \
95 }
96 #define GG(a, b, c, d, x, s, ac) \
97 { \
98 (a) += G((b), (c), (d)) + (x) + (UINT4)(ac); \
99 (a) = ROTATE_LEFT((a), (s)); \
100 (a) += (b); \
101 }
102 #define HH(a, b, c, d, x, s, ac) \
103 { \
104 (a) += H((b), (c), (d)) + (x) + (UINT4)(ac); \
105 (a) = ROTATE_LEFT((a), (s)); \
106 (a) += (b); \
107 }
108 #define II(a, b, c, d, x, s, ac) \
109 { \
110 (a) += I((b), (c), (d)) + (x) + (UINT4)(ac); \
111 (a) = ROTATE_LEFT((a), (s)); \
112 (a) += (b); \
113 }
114
115 /*
116 Just a simple method for getting the signature
117 result must be == 16
118 */
119 void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result) {
120 MD5_CTX my_md5;
121
122 MD5Init(&my_md5);
123 (void) MD5Update(&my_md5, key, length);
124 MD5Final(result, &my_md5);
125 }
126
127 /* MD5 initialization. Begins an MD5 operation, writing a new context.
128 */
129 static void MD5Init(MD5_CTX *context) /* context */
130 {
131 context->count[0] = context->count[1] = 0;
132 /* Load magic initialization constants.
133 */
134 context->state[0] = 0x67452301;
135 context->state[1] = 0xefcdab89;
136 context->state[2] = 0x98badcfe;
137 context->state[3] = 0x10325476;
138 }
139
140 /* MD5 block update operation. Continues an MD5 message-digest
141 operation, processing another message block, and updating the
142 context.
143 */
144
145 static void MD5Update(MD5_CTX *context, /* context */
146 const unsigned char *input, /* input block */
147 unsigned int inputLen) /* length of input block */
148 {
149 unsigned int i, idx, partLen;
150
151 /* Compute number of bytes mod 64 */
152 idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
153
154 /* Update number of bits */
155 if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3))
156 context->count[1]++;
157 context->count[1] += ((UINT4) inputLen >> 29);
158
159 partLen = 64 - idx;
160
161 /* Transform as many times as possible.
162 */
163 if (inputLen >= partLen) {
164 memcpy((POINTER) &context->buffer[idx], (CONST_POINTER) input, partLen);
165 MD5Transform(context->state, context->buffer);
166
167 for (i = partLen; i + 63 < inputLen; i += 64)
168 MD5Transform(context->state, (CONST_POINTER) &input[i]);
169
170 idx = 0;
171 } else
172 i = 0;
173
174 /* Buffer remaining input */
175 memcpy((POINTER) &context->buffer[idx], (CONST_POINTER) &input[i], inputLen - i);
176 }
177
178 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
179 the message digest and zeroizing the context.
180 */
181
182 static void MD5Final(unsigned char digest[16], /* message digest */
183 MD5_CTX *context) /* context */
184 {
185 unsigned char bits[8];
186 unsigned int idx, padLen;
187
188 /* Save number of bits */
189 Encode(bits, context->count, 8);
190
191 /* Pad out to 56 mod 64.
192 */
193 idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
194 padLen = (idx < 56) ? (56 - idx) : (120 - idx);
195 MD5Update(context, PADDING, padLen);
196
197 /* Append length (before padding) */
198 MD5Update(context, bits, 8);
199
200 /* Store state in digest */
201 Encode(digest, context->state, 16);
202
203 /* Zeroize sensitive information.
204 */
205 memset((POINTER) context, 0, sizeof(*context));
206 }
207
208 /* MD5 basic transformation. Transforms state based on block.
209 */
210 static void MD5Transform(UINT4 state[4], const unsigned char block[64]) {
211 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
212
213 Decode(x, block, 64);
214
215 /* Round 1 */
216 FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
217 FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
218 FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
219 FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
220 FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
221 FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
222 FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
223 FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
224 FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
225 FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
226 FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
227 FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
228 FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
229 FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
230 FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
231 FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
232
233 /* Round 2 */
234 GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
235 GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
236 GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
237 GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
238 GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
239 GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
240 GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
241 GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
242 GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
243 GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
244 GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
245 GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
246 GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
247 GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
248 GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
249 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
250
251 /* Round 3 */
252 HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
253 HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
254 HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
255 HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
256 HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
257 HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
258 HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
259 HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
260 HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
261 HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
262 HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
263 HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
264 HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
265 HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
266 HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
267 HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
268
269 /* Round 4 */
270 II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
271 II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
272 II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
273 II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
274 II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
275 II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
276 II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
277 II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
278 II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
279 II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
280 II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
281 II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
282 II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
283 II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
284 II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
285 II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
286
287 state[0] += a;
288 state[1] += b;
289 state[2] += c;
290 state[3] += d;
291
292 /* Zeroize sensitive information.
293 */
294 memset((POINTER) x, 0, sizeof(x));
295 }
296
297 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
298 a multiple of 4.
299 */
300 static void Encode(unsigned char *output, UINT4 *input, unsigned int len) {
301 unsigned int i, j;
302
303 for (i = 0, j = 0; j < len; i++, j += 4) {
304 output[j] = (unsigned char) (input[i] & 0xff);
305 output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
306 output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
307 output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
308 }
309 }
310
311 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
312 a multiple of 4.
313 */
314 static void Decode(UINT4 *output, const unsigned char *input, unsigned int len) {
315 unsigned int i, j;
316
317 for (i = 0, j = 0; j < len; i++, j += 4)
318 output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | (((UINT4) input[j + 2]) << 16)
319 | (((UINT4) input[j + 3]) << 24);
320 }
321
322 uint32_t hashkit_md5(const char *key, size_t key_length, void *context) {
323 unsigned char results[16];
324 (void) context;
325
326 md5_signature((unsigned char *) key, (unsigned int) key_length, results);
327
328 return ((uint32_t)(results[3] & 0xFF) << 24) | ((uint32_t)(results[2] & 0xFF) << 16)
329 | ((uint32_t)(results[1] & 0xFF) << 8) | (results[0] & 0xFF);
330 }