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