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