* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / MD5CryptoServiceProvider.cs
1 //
2 // System.Security.Cryptography MD5CryptoServiceProvider Class implementation
3 //
4 // Authors:
5 //      Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
6 //      Sebastien Pouliot (sebastien@ximian.com)
7 //
8 // Copyright 2001 by Matthew S. Ford.
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Runtime.InteropServices;
32
33 namespace System.Security.Cryptography {
34
35 #if NET_1_0
36         public class MD5CryptoServiceProvider : MD5 {
37 #else
38         #if NET_2_0
39         [ComVisible (true)]
40         #endif
41         public sealed class MD5CryptoServiceProvider : MD5 {
42 #endif
43                 private const int BLOCK_SIZE_BYTES =  64;
44                 private const int HASH_SIZE_BYTES  =  16;
45                 private uint[] _H;
46                 private uint[] buff;
47                 private ulong count;
48                 private byte[] _ProcessingBuffer;   // Used to start data when passed less than a block worth.
49                 private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
50         
51                 public MD5CryptoServiceProvider () 
52                 {
53                         _H = new uint[4];
54                         buff = new uint[16];
55                         _ProcessingBuffer = new byte [BLOCK_SIZE_BYTES];
56
57                         Initialize();
58                 }
59
60                 ~MD5CryptoServiceProvider () 
61                 {
62                         Dispose (false);
63                 }
64
65                 protected override void Dispose (bool disposing) 
66                 {
67                         if (_ProcessingBuffer != null) {
68                                 Array.Clear (_ProcessingBuffer, 0, _ProcessingBuffer.Length);
69                                 _ProcessingBuffer = null;
70                         }
71                         if (_H != null) {
72                                 Array.Clear (_H, 0, _H.Length);
73                                 _H = null;
74                         }
75                         if (buff != null) {
76                                 Array.Clear (buff, 0, buff.Length);
77                                 buff = null;
78                         }
79                 }
80
81                 protected override void HashCore (byte[] rgb, int start, int size) 
82                 {
83                         int i;
84                         State = 1;
85
86                         if (_ProcessingBufferCount != 0) {
87                                 if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
88                                         System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
89                                         _ProcessingBufferCount += size;
90                                         return;
91                                 }
92                                 else {
93                                         i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
94                                         System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
95                                         ProcessBlock (_ProcessingBuffer, 0);
96                                         _ProcessingBufferCount = 0;
97                                         start += i;
98                                         size -= i;
99                                 }
100                         }
101
102                         for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
103                                 ProcessBlock (rgb, start+i);
104                         }
105
106                         if (size%BLOCK_SIZE_BYTES != 0) {
107                                 System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
108                                 _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
109                         }
110                 }
111         
112                 protected override byte[] HashFinal () 
113                 {
114                         byte[] hash = new byte[16];
115                         int i, j;
116
117                         ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
118
119                         for (i=0; i<4; i++) {
120                                 for (j=0; j<4; j++) {
121                                         hash[i*4+j] = (byte)(_H[i] >> j*8);
122                                 }
123                         }
124
125                         return hash;
126                 }
127
128                 public override void Initialize () 
129                 {
130                         count = 0;
131                         _ProcessingBufferCount = 0;
132
133                         _H[0] = 0x67452301;
134                         _H[1] = 0xefcdab89;
135                         _H[2] = 0x98badcfe;
136                         _H[3] = 0x10325476;
137                 }
138
139                 private void ProcessBlock (byte[] inputBuffer, int inputOffset) 
140                 {
141                         uint a, b, c, d;
142                         int i;
143                 
144                         count += BLOCK_SIZE_BYTES;
145                 
146                         for (i=0; i<16; i++) {
147                                 buff[i] = (uint)(inputBuffer[inputOffset+4*i])
148                                         | (((uint)(inputBuffer[inputOffset+4*i+1])) <<  8)
149                                         | (((uint)(inputBuffer[inputOffset+4*i+2])) << 16)
150                                         | (((uint)(inputBuffer[inputOffset+4*i+3])) << 24);
151                         }
152                 
153                         a = _H[0];
154                         b = _H[1];
155                         c = _H[2];
156                         d = _H[3];
157                 
158                         // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
159                         // Possibly roll up if this changes.
160
161                         // ---- Round 1 --------
162
163                         a += (((c ^ d) & b) ^ d) + (uint) K [0] + buff [0];
164                         a = (a << 7) | (a >> 25);
165                         a += b;
166
167                         d += (((b ^ c) & a) ^ c) + (uint) K [1] + buff [1];
168                         d = (d << 12) | (d >> 20);
169                         d += a;
170
171                         c += (((a ^ b) & d) ^ b) + (uint) K [2] + buff [2];
172                         c = (c << 17) | (c >> 15);
173                         c += d;
174
175                         b += (((d ^ a) & c) ^ a) + (uint) K [3] + buff [3];
176                         b = (b << 22) | (b >> 10);
177                         b += c;
178
179                         a += (((c ^ d) & b) ^ d) + (uint) K [4] + buff [4];
180                         a = (a << 7) | (a >> 25);
181                         a += b;
182
183                         d += (((b ^ c) & a) ^ c) + (uint) K [5] + buff [5];
184                         d = (d << 12) | (d >> 20);
185                         d += a;
186
187                         c += (((a ^ b) & d) ^ b) + (uint) K [6] + buff [6];
188                         c = (c << 17) | (c >> 15);
189                         c += d;
190
191                         b += (((d ^ a) & c) ^ a) + (uint) K [7] + buff [7];
192                         b = (b << 22) | (b >> 10);
193                         b += c;
194
195                         a += (((c ^ d) & b) ^ d) + (uint) K [8] + buff [8];
196                         a = (a << 7) | (a >> 25);
197                         a += b;
198
199                         d += (((b ^ c) & a) ^ c) + (uint) K [9] + buff [9];
200                         d = (d << 12) | (d >> 20);
201                         d += a;
202
203                         c += (((a ^ b) & d) ^ b) + (uint) K [10] + buff [10];
204                         c = (c << 17) | (c >> 15);
205                         c += d;
206
207                         b += (((d ^ a) & c) ^ a) + (uint) K [11] + buff [11];
208                         b = (b << 22) | (b >> 10);
209                         b += c;
210
211                         a += (((c ^ d) & b) ^ d) + (uint) K [12] + buff [12];
212                         a = (a << 7) | (a >> 25);
213                         a += b;
214
215                         d += (((b ^ c) & a) ^ c) + (uint) K [13] + buff [13];
216                         d = (d << 12) | (d >> 20);
217                         d += a;
218
219                         c += (((a ^ b) & d) ^ b) + (uint) K [14] + buff [14];
220                         c = (c << 17) | (c >> 15);
221                         c += d;
222
223                         b += (((d ^ a) & c) ^ a) + (uint) K [15] + buff [15];
224                         b = (b << 22) | (b >> 10);
225                         b += c;
226
227
228                         // ---- Round 2 --------
229   
230                         a += (((b ^ c) & d) ^ c) + (uint) K [16] + buff [1];
231                         a = (a << 5) | (a >> 27);
232                         a += b;
233
234                         d += (((a ^ b) & c) ^ b) + (uint) K [17] + buff [6];
235                         d = (d << 9) | (d >> 23);
236                         d += a;
237
238                         c += (((d ^ a) & b) ^ a) + (uint) K [18] + buff [11];
239                         c = (c << 14) | (c >> 18);
240                         c += d;
241
242                         b += (((c ^ d) & a) ^ d) + (uint) K [19] + buff [0];
243                         b = (b << 20) | (b >> 12);
244                         b += c;
245
246                         a += (((b ^ c) & d) ^ c) + (uint) K [20] + buff [5];
247                         a = (a << 5) | (a >> 27);
248                         a += b;
249
250                         d += (((a ^ b) & c) ^ b) + (uint) K [21] + buff [10];
251                         d = (d << 9) | (d >> 23);
252                         d += a;
253
254                         c += (((d ^ a) & b) ^ a) + (uint) K [22] + buff [15];
255                         c = (c << 14) | (c >> 18);
256                         c += d;
257
258                         b += (((c ^ d) & a) ^ d) + (uint) K [23] + buff [4];
259                         b = (b << 20) | (b >> 12);
260                         b += c;
261
262                         a += (((b ^ c) & d) ^ c) + (uint) K [24] + buff [9];
263                         a = (a << 5) | (a >> 27);
264                         a += b;
265
266                         d += (((a ^ b) & c) ^ b) + (uint) K [25] + buff [14];
267                         d = (d << 9) | (d >> 23);
268                         d += a;
269
270                         c += (((d ^ a) & b) ^ a) + (uint) K [26] + buff [3];
271                         c = (c << 14) | (c >> 18);
272                         c += d;
273
274                         b += (((c ^ d) & a) ^ d) + (uint) K [27] + buff [8];
275                         b = (b << 20) | (b >> 12);
276                         b += c;
277
278                         a += (((b ^ c) & d) ^ c) + (uint) K [28] + buff [13];
279                         a = (a << 5) | (a >> 27);
280                         a += b;
281
282                         d += (((a ^ b) & c) ^ b) + (uint) K [29] + buff [2];
283                         d = (d << 9) | (d >> 23);
284                         d += a;
285
286                         c += (((d ^ a) & b) ^ a) + (uint) K [30] + buff [7];
287                         c = (c << 14) | (c >> 18);
288                         c += d;
289
290                         b += (((c ^ d) & a) ^ d) + (uint) K [31] + buff [12];
291                         b = (b << 20) | (b >> 12);
292                         b += c;
293
294
295                         // ---- Round 3 --------
296   
297                         a += (b ^ c ^ d) + (uint) K [32] + buff [5];
298                         a = (a << 4) | (a >> 28);
299                         a += b;
300
301                         d += (a ^ b ^ c) + (uint) K [33] + buff [8];
302                         d = (d << 11) | (d >> 21);
303                         d += a;
304
305                         c += (d ^ a ^ b) + (uint) K [34] + buff [11];
306                         c = (c << 16) | (c >> 16);
307                         c += d;
308
309                         b += (c ^ d ^ a) + (uint) K [35] + buff [14];
310                         b = (b << 23) | (b >> 9);
311                         b += c;
312
313                         a += (b ^ c ^ d) + (uint) K [36] + buff [1];
314                         a = (a << 4) | (a >> 28);
315                         a += b;
316
317                         d += (a ^ b ^ c) + (uint) K [37] + buff [4];
318                         d = (d << 11) | (d >> 21);
319                         d += a;
320
321                         c += (d ^ a ^ b) + (uint) K [38] + buff [7];
322                         c = (c << 16) | (c >> 16);
323                         c += d;
324
325                         b += (c ^ d ^ a) + (uint) K [39] + buff [10];
326                         b = (b << 23) | (b >> 9);
327                         b += c;
328
329                         a += (b ^ c ^ d) + (uint) K [40] + buff [13];
330                         a = (a << 4) | (a >> 28);
331                         a += b;
332
333                         d += (a ^ b ^ c) + (uint) K [41] + buff [0];
334                         d = (d << 11) | (d >> 21);
335                         d += a;
336
337                         c += (d ^ a ^ b) + (uint) K [42] + buff [3];
338                         c = (c << 16) | (c >> 16);
339                         c += d;
340
341                         b += (c ^ d ^ a) + (uint) K [43] + buff [6];
342                         b = (b << 23) | (b >> 9);
343                         b += c;
344
345                         a += (b ^ c ^ d) + (uint) K [44] + buff [9];
346                         a = (a << 4) | (a >> 28);
347                         a += b;
348
349                         d += (a ^ b ^ c) + (uint) K [45] + buff [12];
350                         d = (d << 11) | (d >> 21);
351                         d += a;
352
353                         c += (d ^ a ^ b) + (uint) K [46] + buff [15];
354                         c = (c << 16) | (c >> 16);
355                         c += d;
356
357                         b += (c ^ d ^ a) + (uint) K [47] + buff [2];
358                         b = (b << 23) | (b >> 9);
359                         b += c;
360
361
362                         // ---- Round 4 --------
363   
364                         a += (((~d) | b) ^ c) + (uint) K [48] + buff [0];
365                         a = (a << 6) | (a >> 26);
366                         a += b;
367
368                         d += (((~c) | a) ^ b) + (uint) K [49] + buff [7];
369                         d = (d << 10) | (d >> 22);
370                         d += a;
371
372                         c += (((~b) | d) ^ a) + (uint) K [50] + buff [14];
373                         c = (c << 15) | (c >> 17);
374                         c += d;
375
376                         b += (((~a) | c) ^ d) + (uint) K [51] + buff [5];
377                         b = (b << 21) | (b >> 11);
378                         b += c;
379
380                         a += (((~d) | b) ^ c) + (uint) K [52] + buff [12];
381                         a = (a << 6) | (a >> 26);
382                         a += b;
383
384                         d += (((~c) | a) ^ b) + (uint) K [53] + buff [3];
385                         d = (d << 10) | (d >> 22);
386                         d += a;
387
388                         c += (((~b) | d) ^ a) + (uint) K [54] + buff [10];
389                         c = (c << 15) | (c >> 17);
390                         c += d;
391
392                         b += (((~a) | c) ^ d) + (uint) K [55] + buff [1];
393                         b = (b << 21) | (b >> 11);
394                         b += c;
395
396                         a += (((~d) | b) ^ c) + (uint) K [56] + buff [8];
397                         a = (a << 6) | (a >> 26);
398                         a += b;
399
400                         d += (((~c) | a) ^ b) + (uint) K [57] + buff [15];
401                         d = (d << 10) | (d >> 22);
402                         d += a;
403
404                         c += (((~b) | d) ^ a) + (uint) K [58] + buff [6];
405                         c = (c << 15) | (c >> 17);
406                         c += d;
407
408                         b += (((~a) | c) ^ d) + (uint) K [59] + buff [13];
409                         b = (b << 21) | (b >> 11);
410                         b += c;
411
412                         a += (((~d) | b) ^ c) + (uint) K [60] + buff [4];
413                         a = (a << 6) | (a >> 26);
414                         a += b;
415
416                         d += (((~c) | a) ^ b) + (uint) K [61] + buff [11];
417                         d = (d << 10) | (d >> 22);
418                         d += a;
419
420                         c += (((~b) | d) ^ a) + (uint) K [62] + buff [2];
421                         c = (c << 15) | (c >> 17);
422                         c += d;
423
424                         b += (((~a) | c) ^ d) + (uint) K [63] + buff [9];
425                         b = (b << 21) | (b >> 11);
426                         b += c;
427
428                         _H [0] += a;
429                         _H [1] += b;
430                         _H [2] += c;
431                         _H [3] += d;
432                 }
433                 
434                 private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount) 
435                 {
436                         ulong total = count + (ulong)inputCount;
437                         int paddingSize = (int)(56 - total % BLOCK_SIZE_BYTES);
438
439                         if (paddingSize < 1)
440                                 paddingSize += BLOCK_SIZE_BYTES;
441
442                         byte[] fooBuffer = new byte [inputCount+paddingSize+8];
443
444                         for (int i=0; i<inputCount; i++) {
445                                 fooBuffer[i] = inputBuffer[i+inputOffset];
446                         }
447
448                         fooBuffer[inputCount] = 0x80;
449                         for (int i=inputCount+1; i<inputCount+paddingSize; i++) {
450                                 fooBuffer[i] = 0x00;
451                         }
452
453                         // I deal in bytes. The algorithm deals in bits.
454                         ulong size = total << 3;
455                         AddLength (size, fooBuffer, inputCount+paddingSize);
456                         ProcessBlock (fooBuffer, 0);
457
458                         if (inputCount+paddingSize+8 == 128) {
459                                 ProcessBlock(fooBuffer, 64);
460                         }
461                 }
462
463                 internal void AddLength (ulong length, byte[] buffer, int position)
464                 {
465                         buffer [position++] = (byte)(length);
466                         buffer [position++] = (byte)(length >>  8);
467                         buffer [position++] = (byte)(length >> 16);
468                         buffer [position++] = (byte)(length >> 24);
469                         buffer [position++] = (byte)(length >> 32);
470                         buffer [position++] = (byte)(length >> 40);
471                         buffer [position++] = (byte)(length >> 48);
472                         buffer [position]   = (byte)(length >> 56);
473                 }
474
475                 private readonly static uint[] K = {
476                         0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
477                         0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 
478                         0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
479                         0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
480                         0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
481                         0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
482                         0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
483                         0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
484                         0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
485                         0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
486                         0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
487                         0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
488                         0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
489                         0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
490                         0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
491                         0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
492                 };
493         }
494 }
495