aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llmd5.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llcommon/llmd5.cpp')
-rw-r--r--linden/indra/llcommon/llmd5.cpp531
1 files changed, 531 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llmd5.cpp b/linden/indra/llcommon/llmd5.cpp
new file mode 100644
index 0000000..a0ac92f
--- /dev/null
+++ b/linden/indra/llcommon/llmd5.cpp
@@ -0,0 +1,531 @@
1/**
2 * @file llmd5.cpp
3 *
4 * $LicenseInfo:firstyear=2001&license=viewergpl$
5 *
6 * Copyright (c) 2001-2008, Linden Research, Inc.
7 *
8 * Second Life Viewer Source Code
9 * The source code in this file ("Source Code") is provided by Linden Lab
10 * to you under the terms of the GNU General Public License, version 2.0
11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
20 *
21 * By copying, modifying or distributing this software, you acknowledge
22 * that you have read and understood your obligations described above,
23 * and agree to abide by those obligations.
24 *
25 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
26 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
27 * COMPLETENESS OR PERFORMANCE.
28 * $/LicenseInfo$
29 */
30
31// llMD5.CC - source code for the C++/object oriented translation and
32// modification of MD5.
33//
34// Adapted to Linden Lab by Frank Filipanits, 6/25/2002
35// Fixed potential memory leak, James Cook, 6/27/2002
36
37// Translation and modification (c) 1995 by Mordechai T. Abzug
38
39// This translation/ modification is provided "as is," without express or
40// implied warranty of any kind.
41
42// The translator/ modifier does not claim (1) that MD5 will do what you think
43// it does; (2) that this translation/ modification is accurate; or (3) that
44// this software is "merchantible." (Language for this disclaimer partially
45// copied from the disclaimer below).
46
47/* based on:
48
49 MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
50 MDDRIVER.C - test driver for MD2, MD4 and MD5
51
52
53 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
54rights reserved.
55
56License to copy and use this software is granted provided that it
57is identified as the "RSA Data Security, Inc. MD5 Message-Digest
58Algorithm" in all material mentioning or referencing this software
59or this function.
60
61License is also granted to make and use derivative works provided
62that such works are identified as "derived from the RSA Data
63Security, Inc. MD5 Message-Digest Algorithm" in all material
64mentioning or referencing the derived work.
65
66RSA Data Security, Inc. makes no representations concerning either
67the merchantability of this software or the suitability of this
68software for any particular purpose. It is provided "as is"
69without express or implied warranty of any kind.
70
71These notices must be retained in any copies of any part of this
72documentation and/or software.
73
74 */
75
76
77
78
79
80#include "linden_common.h"
81
82#include "llmd5.h"
83
84#include <cassert>
85
86// how many bytes to grab at a time when checking files
87const int LLMD5::BLOCK_LEN = 4096;
88
89
90// LLMD5 simple initialization method
91
92LLMD5::LLMD5()
93{
94 init();
95}
96
97
98
99
100// MD5 block update operation. Continues an MD5 message-digest
101// operation, processing another message block, and updating the
102// context.
103
104void LLMD5::update (const uint1 *input, const uint4 input_length) {
105
106 uint4 input_index, buffer_index;
107 uint4 buffer_space; // how much space is left in buffer
108
109 if (finalized){ // so we can't update!
110 std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl;
111 return;
112 }
113
114 // Compute number of bytes mod 64
115 buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
116
117 // Update number of bits
118 if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
119 count[1]++;
120
121 count[1] += ((uint4)input_length >> 29);
122
123
124 buffer_space = 64 - buffer_index; // how much space is left in buffer
125
126 // Transform as many times as possible.
127 if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
128 // fill the rest of the buffer and transform
129 memcpy( /* Flawfinder: ignore */
130 buffer + buffer_index,
131 input,
132 buffer_space);
133 transform (buffer);
134
135 // now, transform each 64-byte piece of the input, bypassing the buffer
136 if (input == NULL || input_length == 0){
137 std::cerr << "LLMD5::update: Invalid input!" << std::endl;
138 return;
139 }
140
141 for (input_index = buffer_space; input_index + 63 < input_length;
142 input_index += 64)
143 transform (input+input_index);
144
145 buffer_index = 0; // so we can buffer remaining
146 }
147 else
148 input_index=0; // so we can buffer the whole input
149
150
151 // and here we do the buffering:
152 memcpy(buffer+buffer_index, input+input_index, input_length-input_index); /* Flawfinder: ignore */
153}
154
155
156
157// MD5 update for files.
158// Like above, except that it works on files (and uses above as a primitive.)
159
160void LLMD5::update(FILE* file){
161
162 unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
163 int len;
164
165 while ( (len=(int)fread(buffer, 1, BLOCK_LEN, file)) )
166 update(buffer, len);
167
168 fclose (file);
169
170}
171
172
173
174
175
176
177// MD5 update for istreams.
178// Like update for files; see above.
179
180void LLMD5::update(std::istream& stream){
181
182 unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
183 int len;
184
185 while (stream.good()){
186 stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable.
187 len=stream.gcount();
188 update(buffer, len);
189 }
190
191}
192
193
194
195
196
197// MD5 finalization. Ends an MD5 message-digest operation, writing the
198// the message digest and zeroizing the context.
199
200
201void LLMD5::finalize (){
202
203 unsigned char bits[8]; /* Flawfinder: ignore */
204 unsigned int index, padLen;
205 static uint1 PADDING[64]={
206 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
209 };
210
211 if (finalized){
212 std::cerr << "LLMD5::finalize: Already finalized this digest!" << std::endl;
213 return;
214 }
215
216 // Save number of bits
217 encode (bits, count, 8);
218
219 // Pad out to 56 mod 64.
220 index = (uint4) ((count[0] >> 3) & 0x3f);
221 padLen = (index < 56) ? (56 - index) : (120 - index);
222 update (PADDING, padLen);
223
224 // Append length (before padding)
225 update (bits, 8);
226
227 // Store state in digest
228 encode (digest, state, 16);
229
230 // Zeroize sensitive information
231 memset (buffer, 0, sizeof(*buffer));
232
233 finalized=1;
234
235}
236
237
238
239
240LLMD5::LLMD5(FILE *file){
241
242 init(); // must be called be all constructors
243 update(file);
244 finalize ();
245}
246
247
248
249
250LLMD5::LLMD5(std::istream& stream){
251
252 init(); // must called by all constructors
253 update (stream);
254 finalize();
255}
256
257// Digest a string of the format ("%s:%i" % (s, number))
258LLMD5::LLMD5(const unsigned char *string, const unsigned int number)
259{
260 const char *colon = ":";
261 char tbuf[16]; /* Flawfinder: ignore */
262 init();
263 update(string, (U32)strlen((const char *) string)); /* Flawfinder: ignore */
264 update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
265 snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */
266 update((const unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
267 finalize();
268}
269
270// Digest a string
271LLMD5::LLMD5(const unsigned char *s)
272{
273 init();
274 update(s, (U32)strlen((const char *) s)); /* Flawfinder: ignore */
275 finalize();
276}
277
278void LLMD5::raw_digest(unsigned char *s)
279{
280 if (!finalized)
281 {
282 std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't "<<
283 "finalized the digest!" << std::endl;
284 s[0] = '\0';
285 return;
286 }
287
288 memcpy(s, digest, 16); /* Flawfinder: ignore */
289 return;
290}
291
292
293
294void LLMD5::hex_digest(char *s)
295{
296 int i;
297
298 if (!finalized)
299 {
300 std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't "<<
301 "finalized the digest!" <<std::endl;
302 s[0] = '\0';
303 return;
304 }
305
306 for (i=0; i<16; i++)
307 {
308 sprintf(s+i*2, "%02x", digest[i]); /* Flawfinder: ignore */
309 }
310
311 s[32]='\0';
312
313 return;
314}
315
316
317
318
319
320std::ostream& operator<<(std::ostream &stream, LLMD5 context)
321{
322 char s[33]; /* Flawfinder: ignore */
323 context.hex_digest(s);
324 stream << s;
325 return stream;
326}
327
328
329
330
331// PRIVATE METHODS:
332
333
334
335void LLMD5::init(){
336 finalized=0; // we just started!
337
338 // Nothing counted, so count=0
339 count[0] = 0;
340 count[1] = 0;
341
342 // Load magic initialization constants.
343 state[0] = 0x67452301;
344 state[1] = 0xefcdab89;
345 state[2] = 0x98badcfe;
346 state[3] = 0x10325476;
347}
348
349
350
351// Constants for MD5Transform routine.
352// Although we could use C++ style constants, defines are actually better,
353// since they let us easily evade scope clashes.
354
355#define S11 7
356#define S12 12
357#define S13 17
358#define S14 22
359#define S21 5
360#define S22 9
361#define S23 14
362#define S24 20
363#define S31 4
364#define S32 11
365#define S33 16
366#define S34 23
367#define S41 6
368#define S42 10
369#define S43 15
370#define S44 21
371
372// #defines are faster then inline, etc because the compiler is not required to inline.
373// Timing tests prove that this works ~40% faster on win with msvc++2k3 over using static inline.
374
375/* F, G, H and I are basic MD5 functions.
376 */
377#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
378#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
379#define H(x, y, z) ((x) ^ (y) ^ (z))
380#define I(x, y, z) ((y) ^ ((x) | (~z)))
381
382/* ROTATE_LEFT rotates x left n bits.
383 */
384#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
385
386/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
387Rotation is separate from addition to prevent recomputation.
388 */
389#define FF(a, b, c, d, x, s, ac) { \
390 (a) += F ((b), (c), (d)) + (x) + (U32)(ac); \
391 (a) = ROTATE_LEFT ((a), (s)); \
392 (a) += (b); \
393 }
394#define GG(a, b, c, d, x, s, ac) { \
395 (a) += G ((b), (c), (d)) + (x) + (U32)(ac); \
396 (a) = ROTATE_LEFT ((a), (s)); \
397 (a) += (b); \
398 }
399#define HH(a, b, c, d, x, s, ac) { \
400 (a) += H ((b), (c), (d)) + (x) + (U32)(ac); \
401 (a) = ROTATE_LEFT ((a), (s)); \
402 (a) += (b); \
403 }
404#define II(a, b, c, d, x, s, ac) { \
405 (a) += I ((b), (c), (d)) + (x) + (U32)(ac); \
406 (a) = ROTATE_LEFT ((a), (s)); \
407 (a) += (b); \
408 }
409
410
411
412// LLMD5 basic transformation. Transforms state based on block.
413void LLMD5::transform (const U8 block[64]){
414
415 uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
416
417 decode (x, block, 64);
418
419 assert(!finalized); // not just a user error, since the method is private
420
421 /* Round 1 */
422 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
423 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
424 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
425 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
426 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
427 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
428 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
429 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
430 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
431 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
432 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
433 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
434 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
435 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
436 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
437 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
438
439 /* Round 2 */
440 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
441 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
442 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
443 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
444 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
445 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
446 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
447 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
448 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
449 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
450 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
451 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
452 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
453 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
454 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
455 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
456
457 /* Round 3 */
458 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
459 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
460 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
461 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
462 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
463 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
464 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
465 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
466 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
467 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
468 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
469 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
470 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
471 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
472 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
473 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
474
475 /* Round 4 */
476 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
477 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
478 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
479 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
480 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
481 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
482 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
483 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
484 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
485 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
486 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
487 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
488 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
489 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
490 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
491 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
492
493 state[0] += a;
494 state[1] += b;
495 state[2] += c;
496 state[3] += d;
497
498 // Zeroize sensitive information.
499 memset ( (uint1 *) x, 0, sizeof(x));
500
501}
502
503
504
505// Encodes input (UINT4) into output (unsigned char). Assumes len is
506// a multiple of 4.
507void LLMD5::encode (uint1 *output, const uint4 *input, const uint4 len) {
508
509 unsigned int i, j;
510
511 for (i = 0, j = 0; j < len; i++, j += 4) {
512 output[j] = (uint1) (input[i] & 0xff);
513 output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
514 output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
515 output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
516 }
517}
518
519
520
521
522// Decodes input (unsigned char) into output (UINT4). Assumes len is
523// a multiple of 4.
524void LLMD5::decode (uint4 *output, const uint1 *input, const uint4 len){
525
526 unsigned int i, j;
527
528 for (i = 0, j = 0; j < len; i++, j += 4)
529 output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
530 (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
531}