* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / Npgsql / Npgsql / 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 (spouliot@motus.com)
7 //
8 // Copyright 2001 by Matthew S. Ford.
9 //
10 // Comment: Adapted to the Project from Mono CVS as Sebastien Pouliot suggested to enable
11 // support of Npgsql MD5 authentication in platforms which don't have support for MD5 algorithm.
12 //
13
14
15 using System;
16
17
18 namespace Npgsql
19 {
20     /// <summary>
21     /// C# implementation of the MD5 cryptographic hash function.
22     /// </summary>
23 #if USE_VERSION_1_0
24     internal class MD5CryptoServiceProvider : MD5
25     {
26 #else
27     internal sealed class MD5CryptoServiceProvider : MD5
28     {
29 #endif
30         private const int BLOCK_SIZE_BYTES =  64;
31         private const int HASH_SIZE_BYTES  =  16;
32         private const int HASH_SIZE_BITS   = 128;
33         [CLSCompliant(false)] private uint[] _H;
34         [CLSCompliant(false)] private uint count;
35         private byte[] _ProcessingBuffer;   // Used to start data when passed less than a block worth.
36         private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
37
38         /// <summary>
39         /// Creates a new MD5CryptoServiceProvider.
40         /// </summary>
41         public MD5CryptoServiceProvider ()
42         {
43             _H = new uint[4];
44             HashSizeValue = HASH_SIZE_BITS;
45             _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
46
47             Initialize();
48         }
49
50         ~MD5CryptoServiceProvider ()
51         {
52             Dispose (false);
53         }
54
55         protected override void Dispose (bool disposing)
56         {
57             // nothing to do (managed implementation)
58         }
59
60         /// <summary>
61         /// Drives the hashing function.
62         /// </summary>
63         /// <param name="rgb">Byte array containing the data to hash.</param>
64         /// <param name="start">Where in the input buffer to start.</param>
65         /// <param name="size">Size in bytes of the data in the buffer to hash.</param>
66         protected override void HashCore (byte[] rgb, int start, int size)
67         {
68             int i;
69             State = 1;
70
71             if (_ProcessingBufferCount != 0)
72             {
73                 if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount))
74                 {
75                     System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
76                     _ProcessingBufferCount += size;
77                     return;
78                 }
79                 else
80                 {
81                     i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
82                     System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
83                     ProcessBlock (_ProcessingBuffer, 0);
84                     _ProcessingBufferCount = 0;
85                     start += i;
86                     size -= i;
87                 }
88             }
89
90             for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES)
91             {
92                 ProcessBlock (rgb, start+i);
93             }
94
95             if (size%BLOCK_SIZE_BYTES != 0)
96             {
97                 System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
98                 _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
99             }
100         }
101
102         /// <summary>
103         /// This finalizes the hash.  Takes the data from the chaining variables and returns it.
104         /// </summary>
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             {
114                 for (j=0; j<4; j++)
115                 {
116                     hash[i*4+j] = (byte)(_H[i] >> j*8);
117                 }
118             }
119
120             return hash;
121         }
122
123         /// <summary>
124         /// Resets the class after use.  Called automatically after hashing is done.
125         /// </summary>
126         public override void Initialize ()
127         {
128             count = 0;
129             _ProcessingBufferCount = 0;
130
131             _H[0] = 0x67452301;
132             _H[1] = 0xefcdab89;
133             _H[2] = 0x98badcfe;
134             _H[3] = 0x10325476;
135         }
136
137         /// <summary>
138         /// This is the meat of the hash function.  It is what processes each block one at a time.
139         /// </summary>
140         /// <param name="inputBuffer">Byte array to process data from.</param>
141         /// <param name="inputOffset">Where in the byte array to start processing.</param>
142         private void ProcessBlock (byte[] inputBuffer, int inputOffset)
143         {
144             uint[] buff = new uint[16];
145             uint a, b, c, d;
146             int i;
147
148             count += BLOCK_SIZE_BYTES;
149
150             for (i=0; i<16; i++)
151             {
152                 buff[i] = (uint)(inputBuffer[inputOffset+4*i])
153                           | (((uint)(inputBuffer[inputOffset+4*i+1])) <<  8)
154                           | (((uint)(inputBuffer[inputOffset+4*i+2])) << 16)
155                           | (((uint)(inputBuffer[inputOffset+4*i+3])) << 24);
156             }
157
158             a = _H[0];
159             b = _H[1];
160             c = _H[2];
161             d = _H[3];
162
163             // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
164             // Possibly roll up if this changes.
165
166
167             // ---- Round 1 --------
168
169             a += (((c ^ d) & b) ^ d) + (uint) Constants.C0 + buff [0];
170             a = (a << 7) | (a >> 25);
171             a += b;
172
173             d += (((b ^ c) & a) ^ c) + (uint) Constants.C1 + buff [1];
174             d = (d << 12) | (d >> 20);
175             d += a;
176
177             c += (((a ^ b) & d) ^ b) + (uint) Constants.C2 + buff [2];
178             c = (c << 17) | (c >> 15);
179             c += d;
180
181             b += (((d ^ a) & c) ^ a) + (uint) Constants.C3 + buff [3];
182             b = (b << 22) | (b >> 10);
183             b += c;
184
185             a += (((c ^ d) & b) ^ d) + (uint) Constants.C4 + buff [4];
186             a = (a << 7) | (a >> 25);
187             a += b;
188
189             d += (((b ^ c) & a) ^ c) + (uint) Constants.C5 + buff [5];
190             d = (d << 12) | (d >> 20);
191             d += a;
192
193             c += (((a ^ b) & d) ^ b) + (uint) Constants.C6 + buff [6];
194             c = (c << 17) | (c >> 15);
195             c += d;
196
197             b += (((d ^ a) & c) ^ a) + (uint) Constants.C7 + buff [7];
198             b = (b << 22) | (b >> 10);
199             b += c;
200
201             a += (((c ^ d) & b) ^ d) + (uint) Constants.C8 + buff [8];
202             a = (a << 7) | (a >> 25);
203             a += b;
204
205             d += (((b ^ c) & a) ^ c) + (uint) Constants.C9 + buff [9];
206             d = (d << 12) | (d >> 20);
207             d += a;
208
209             c += (((a ^ b) & d) ^ b) + (uint) Constants.C10 + buff [10];
210             c = (c << 17) | (c >> 15);
211             c += d;
212
213             b += (((d ^ a) & c) ^ a) + (uint) Constants.C11 + buff [11];
214             b = (b << 22) | (b >> 10);
215             b += c;
216
217             a += (((c ^ d) & b) ^ d) + (uint) Constants.C12 + buff [12];
218             a = (a << 7) | (a >> 25);
219             a += b;
220
221             d += (((b ^ c) & a) ^ c) + (uint) Constants.C13 + buff [13];
222             d = (d << 12) | (d >> 20);
223             d += a;
224
225             c += (((a ^ b) & d) ^ b) + (uint) Constants.C14 + buff [14];
226             c = (c << 17) | (c >> 15);
227             c += d;
228
229             b += (((d ^ a) & c) ^ a) + (uint) Constants.C15 + buff [15];
230             b = (b << 22) | (b >> 10);
231             b += c;
232
233
234             // ---- Round 2 --------
235
236             a += (((b ^ c) & d) ^ c) + (uint) Constants.C16 + buff [1];
237             a = (a << 5) | (a >> 27);
238             a += b;
239
240             d += (((a ^ b) & c) ^ b) + (uint) Constants.C17 + buff [6];
241             d = (d << 9) | (d >> 23);
242             d += a;
243
244             c += (((d ^ a) & b) ^ a) + (uint) Constants.C18 + buff [11];
245             c = (c << 14) | (c >> 18);
246             c += d;
247
248             b += (((c ^ d) & a) ^ d) + (uint) Constants.C19 + buff [0];
249             b = (b << 20) | (b >> 12);
250             b += c;
251
252             a += (((b ^ c) & d) ^ c) + (uint) Constants.C20 + buff [5];
253             a = (a << 5) | (a >> 27);
254             a += b;
255
256             d += (((a ^ b) & c) ^ b) + (uint) Constants.C21 + buff [10];
257             d = (d << 9) | (d >> 23);
258             d += a;
259
260             c += (((d ^ a) & b) ^ a) + (uint) Constants.C22 + buff [15];
261             c = (c << 14) | (c >> 18);
262             c += d;
263
264             b += (((c ^ d) & a) ^ d) + (uint) Constants.C23 + buff [4];
265             b = (b << 20) | (b >> 12);
266             b += c;
267
268             a += (((b ^ c) & d) ^ c) + (uint) Constants.C24 + buff [9];
269             a = (a << 5) | (a >> 27);
270             a += b;
271
272             d += (((a ^ b) & c) ^ b) + (uint) Constants.C25 + buff [14];
273             d = (d << 9) | (d >> 23);
274             d += a;
275
276             c += (((d ^ a) & b) ^ a) + (uint) Constants.C26 + buff [3];
277             c = (c << 14) | (c >> 18);
278             c += d;
279
280             b += (((c ^ d) & a) ^ d) + (uint) Constants.C27 + buff [8];
281             b = (b << 20) | (b >> 12);
282             b += c;
283
284             a += (((b ^ c) & d) ^ c) + (uint) Constants.C28 + buff [13];
285             a = (a << 5) | (a >> 27);
286             a += b;
287
288             d += (((a ^ b) & c) ^ b) + (uint) Constants.C29 + buff [2];
289             d = (d << 9) | (d >> 23);
290             d += a;
291
292             c += (((d ^ a) & b) ^ a) + (uint) Constants.C30 + buff [7];
293             c = (c << 14) | (c >> 18);
294             c += d;
295
296             b += (((c ^ d) & a) ^ d) + (uint) Constants.C31 + buff [12];
297             b = (b << 20) | (b >> 12);
298             b += c;
299
300
301             // ---- Round 3 --------
302
303             a += (b ^ c ^ d) + (uint) Constants.C32 + buff [5];
304             a = (a << 4) | (a >> 28);
305             a += b;
306
307             d += (a ^ b ^ c) + (uint) Constants.C33 + buff [8];
308             d = (d << 11) | (d >> 21);
309             d += a;
310
311             c += (d ^ a ^ b) + (uint) Constants.C34 + buff [11];
312             c = (c << 16) | (c >> 16);
313             c += d;
314
315             b += (c ^ d ^ a) + (uint) Constants.C35 + buff [14];
316             b = (b << 23) | (b >> 9);
317             b += c;
318
319             a += (b ^ c ^ d) + (uint) Constants.C36 + buff [1];
320             a = (a << 4) | (a >> 28);
321             a += b;
322
323             d += (a ^ b ^ c) + (uint) Constants.C37 + buff [4];
324             d = (d << 11) | (d >> 21);
325             d += a;
326
327             c += (d ^ a ^ b) + (uint) Constants.C38 + buff [7];
328             c = (c << 16) | (c >> 16);
329             c += d;
330
331             b += (c ^ d ^ a) + (uint) Constants.C39 + buff [10];
332             b = (b << 23) | (b >> 9);
333             b += c;
334
335             a += (b ^ c ^ d) + (uint) Constants.C40 + buff [13];
336             a = (a << 4) | (a >> 28);
337             a += b;
338
339             d += (a ^ b ^ c) + (uint) Constants.C41 + buff [0];
340             d = (d << 11) | (d >> 21);
341             d += a;
342
343             c += (d ^ a ^ b) + (uint) Constants.C42 + buff [3];
344             c = (c << 16) | (c >> 16);
345             c += d;
346
347             b += (c ^ d ^ a) + (uint) Constants.C43 + buff [6];
348             b = (b << 23) | (b >> 9);
349             b += c;
350
351             a += (b ^ c ^ d) + (uint) Constants.C44 + buff [9];
352             a = (a << 4) | (a >> 28);
353             a += b;
354
355             d += (a ^ b ^ c) + (uint) Constants.C45 + buff [12];
356             d = (d << 11) | (d >> 21);
357             d += a;
358
359             c += (d ^ a ^ b) + (uint) Constants.C46 + buff [15];
360             c = (c << 16) | (c >> 16);
361             c += d;
362
363             b += (c ^ d ^ a) + (uint) Constants.C47 + buff [2];
364             b = (b << 23) | (b >> 9);
365             b += c;
366
367
368             // ---- Round 4 --------
369
370             a += (((~d) | b) ^ c) + (uint) Constants.C48 + buff [0];
371             a = (a << 6) | (a >> 26);
372             a += b;
373
374             d += (((~c) | a) ^ b) + (uint) Constants.C49 + buff [7];
375             d = (d << 10) | (d >> 22);
376             d += a;
377
378             c += (((~b) | d) ^ a) + (uint) Constants.C50 + buff [14];
379             c = (c << 15) | (c >> 17);
380             c += d;
381
382             b += (((~a) | c) ^ d) + (uint) Constants.C51 + buff [5];
383             b = (b << 21) | (b >> 11);
384             b += c;
385
386             a += (((~d) | b) ^ c) + (uint) Constants.C52 + buff [12];
387             a = (a << 6) | (a >> 26);
388             a += b;
389
390             d += (((~c) | a) ^ b) + (uint) Constants.C53 + buff [3];
391             d = (d << 10) | (d >> 22);
392             d += a;
393
394             c += (((~b) | d) ^ a) + (uint) Constants.C54 + buff [10];
395             c = (c << 15) | (c >> 17);
396             c += d;
397
398             b += (((~a) | c) ^ d) + (uint) Constants.C55 + buff [1];
399             b = (b << 21) | (b >> 11);
400             b += c;
401
402             a += (((~d) | b) ^ c) + (uint) Constants.C56 + buff [8];
403             a = (a << 6) | (a >> 26);
404             a += b;
405
406             d += (((~c) | a) ^ b) + (uint) Constants.C57 + buff [15];
407             d = (d << 10) | (d >> 22);
408             d += a;
409
410             c += (((~b) | d) ^ a) + (uint) Constants.C58 + buff [6];
411             c = (c << 15) | (c >> 17);
412             c += d;
413
414             b += (((~a) | c) ^ d) + (uint) Constants.C59 + buff [13];
415             b = (b << 21) | (b >> 11);
416             b += c;
417
418             a += (((~d) | b) ^ c) + (uint) Constants.C60 + buff [4];
419             a = (a << 6) | (a >> 26);
420             a += b;
421
422             d += (((~c) | a) ^ b) + (uint) Constants.C61 + buff [11];
423             d = (d << 10) | (d >> 22);
424             d += a;
425
426             c += (((~b) | d) ^ a) + (uint) Constants.C62 + buff [2];
427             c = (c << 15) | (c >> 17);
428             c += d;
429
430             b += (((~a) | c) ^ d) + (uint) Constants.C63 + buff [9];
431             b = (b << 21) | (b >> 11);
432             b += c;
433
434
435             _H[0] += a;
436             _H[1] += b;
437             _H[2] += c;
438             _H[3] += d;
439         }
440
441         /// <summary>
442         /// Pads and then processes the final block.
443         /// </summary>
444         /// <param name="inputBuffer">Buffer to grab data from.</param>
445         /// <param name="inputOffset">Position in buffer in bytes to get data from.</param>
446         /// <param name="inputCount">How much data in bytes in the buffer to use.</param>
447         private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
448         {
449             byte[] fooBuffer;
450             int paddingSize;
451             int i;
452             uint size;
453
454             paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
455
456             if (paddingSize < 1)
457                 paddingSize += BLOCK_SIZE_BYTES;
458
459
460             fooBuffer = new byte[inputCount+paddingSize+8];
461
462             for (i=0; i<inputCount; i++)
463             {
464                 fooBuffer[i] = inputBuffer[i+inputOffset];
465             }
466
467             fooBuffer[inputCount] = 0x80;
468             for (i=inputCount+1; i<inputCount+paddingSize; i++)
469             {
470                 fooBuffer[i] = 0x00;
471             }
472
473             size = (uint)(count+inputCount);
474             size *= 8;
475             fooBuffer[inputCount+paddingSize] = (byte)((size) >>  0);
476             fooBuffer[inputCount+paddingSize+1] = (byte)((size) >>  8);
477             fooBuffer[inputCount+paddingSize+2] = (byte)((size) >> 16);
478             fooBuffer[inputCount+paddingSize+3] = (byte)((size) >> 24);
479
480             fooBuffer[inputCount+paddingSize+4]   = 0x00;
481             fooBuffer[inputCount+paddingSize+5] = 0x00;
482             fooBuffer[inputCount+paddingSize+6] = 0x00;
483             fooBuffer[inputCount+paddingSize+7] = 0x00;
484
485             ProcessBlock(fooBuffer, 0);
486
487             if (inputCount+paddingSize+8 == 128)
488             {
489                 ProcessBlock(fooBuffer, 64);
490             }
491         }
492
493     private enum Constants :
494         uint {
495             C0 = 0xd76aa478, C1 = 0xe8c7b756, C2 = 0x242070db,
496             C3 = 0xc1bdceee, C4 = 0xf57c0faf, C5 = 0x4787c62a,
497             C6 = 0xa8304613, C7 = 0xfd469501, C8 = 0x698098d8,
498             C9 = 0x8b44f7af,C10 = 0xffff5bb1,C11 = 0x895cd7be,
499             C12 = 0x6b901122,C13 = 0xfd987193,C14 = 0xa679438e,
500             C15 = 0x49b40821,C16 = 0xf61e2562,C17 = 0xc040b340,
501             C18 = 0x265e5a51,C19 = 0xe9b6c7aa,C20 = 0xd62f105d,
502             C21 = 0x02441453,C22 = 0xd8a1e681,C23 = 0xe7d3fbc8,
503             C24 = 0x21e1cde6,C25 = 0xc33707d6,C26 = 0xf4d50d87,
504             C27 = 0x455a14ed,C28 = 0xa9e3e905,C29 = 0xfcefa3f8,
505             C30 = 0x676f02d9,C31 = 0x8d2a4c8a,C32 = 0xfffa3942,
506             C33 = 0x8771f681,C34 = 0x6d9d6122,C35 = 0xfde5380c,
507             C36 = 0xa4beea44,C37 = 0x4bdecfa9,C38 = 0xf6bb4b60,
508             C39 = 0xbebfbc70,C40 = 0x289b7ec6,C41 = 0xeaa127fa,
509             C42 = 0xd4ef3085,C43 = 0x04881d05,C44 = 0xd9d4d039,
510             C45 = 0xe6db99e5,C46 = 0x1fa27cf8,C47 = 0xc4ac5665,
511             C48 = 0xf4292244,C49 = 0x432aff97,C50 = 0xab9423a7,
512             C51 = 0xfc93a039,C52 = 0x655b59c3,C53 = 0x8f0ccc92,
513             C54 = 0xffeff47d,C55 = 0x85845dd1,C56 = 0x6fa87e4f,
514             C57 = 0xfe2ce6e0,C58 = 0xa3014314,C59 = 0x4e0811a1,
515             C60 = 0xf7537e82,C61 = 0xbd3af235,C62 = 0x2ad7d2bb,
516             C63 = 0xeb86d391
517         }
518
519     }
520 }
521