PageRenderTime 82ms CodeModel.GetById 43ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llmd5.cpp

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