[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / corlib / System.Security.Cryptography / MD5CryptoServiceProvider.cs
blob80c8cb0159b081ada83af9f915e57976bd56790b
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)
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.
31 using System.Runtime.InteropServices;
33 namespace System.Security.Cryptography {
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.
44 public MD5CryptoServiceProvider ()
46 _H = new uint[4];
47 buff = new uint[16];
48 _ProcessingBuffer = new byte [BLOCK_SIZE_BYTES];
50 Initialize();
53 ~MD5CryptoServiceProvider ()
55 Dispose (false);
58 protected override void Dispose (bool disposing)
60 if (_ProcessingBuffer != null) {
61 Array.Clear (_ProcessingBuffer, 0, _ProcessingBuffer.Length);
63 if (_H != null) {
64 Array.Clear (_H, 0, _H.Length);
66 if (buff != null) {
67 Array.Clear (buff, 0, buff.Length);
70 base.Dispose (disposing);
73 protected override void HashCore (byte[] rgb, int ibStart, int cbSize)
75 int i;
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;
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;
93 for (i = 0; i < cbSize - cbSize % BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
94 ProcessBlock (rgb, ibStart + i);
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;
103 protected override byte[] HashFinal ()
105 byte[] hash = new byte[16];
106 int i, j;
108 ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
110 for (i=0; i<4; i++) {
111 for (j=0; j<4; j++) {
112 hash[i*4+j] = (byte)(_H[i] >> j*8);
116 return hash;
119 public override void Initialize ()
121 count = 0;
122 _ProcessingBufferCount = 0;
124 _H[0] = 0x67452301;
125 _H[1] = 0xefcdab89;
126 _H[2] = 0x98badcfe;
127 _H[3] = 0x10325476;
130 private void ProcessBlock (byte[] inputBuffer, int inputOffset)
132 uint a, b, c, d;
133 int i;
135 count += BLOCK_SIZE_BYTES;
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);
144 a = _H[0];
145 b = _H[1];
146 c = _H[2];
147 d = _H[3];
149 // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
150 // Possibly roll up if this changes.
152 // ---- Round 1 --------
154 a += (((c ^ d) & b) ^ d) + (uint) K [0] + buff [0];
155 a = (a << 7) | (a >> 25);
156 a += b;
158 d += (((b ^ c) & a) ^ c) + (uint) K [1] + buff [1];
159 d = (d << 12) | (d >> 20);
160 d += a;
162 c += (((a ^ b) & d) ^ b) + (uint) K [2] + buff [2];
163 c = (c << 17) | (c >> 15);
164 c += d;
166 b += (((d ^ a) & c) ^ a) + (uint) K [3] + buff [3];
167 b = (b << 22) | (b >> 10);
168 b += c;
170 a += (((c ^ d) & b) ^ d) + (uint) K [4] + buff [4];
171 a = (a << 7) | (a >> 25);
172 a += b;
174 d += (((b ^ c) & a) ^ c) + (uint) K [5] + buff [5];
175 d = (d << 12) | (d >> 20);
176 d += a;
178 c += (((a ^ b) & d) ^ b) + (uint) K [6] + buff [6];
179 c = (c << 17) | (c >> 15);
180 c += d;
182 b += (((d ^ a) & c) ^ a) + (uint) K [7] + buff [7];
183 b = (b << 22) | (b >> 10);
184 b += c;
186 a += (((c ^ d) & b) ^ d) + (uint) K [8] + buff [8];
187 a = (a << 7) | (a >> 25);
188 a += b;
190 d += (((b ^ c) & a) ^ c) + (uint) K [9] + buff [9];
191 d = (d << 12) | (d >> 20);
192 d += a;
194 c += (((a ^ b) & d) ^ b) + (uint) K [10] + buff [10];
195 c = (c << 17) | (c >> 15);
196 c += d;
198 b += (((d ^ a) & c) ^ a) + (uint) K [11] + buff [11];
199 b = (b << 22) | (b >> 10);
200 b += c;
202 a += (((c ^ d) & b) ^ d) + (uint) K [12] + buff [12];
203 a = (a << 7) | (a >> 25);
204 a += b;
206 d += (((b ^ c) & a) ^ c) + (uint) K [13] + buff [13];
207 d = (d << 12) | (d >> 20);
208 d += a;
210 c += (((a ^ b) & d) ^ b) + (uint) K [14] + buff [14];
211 c = (c << 17) | (c >> 15);
212 c += d;
214 b += (((d ^ a) & c) ^ a) + (uint) K [15] + buff [15];
215 b = (b << 22) | (b >> 10);
216 b += c;
219 // ---- Round 2 --------
221 a += (((b ^ c) & d) ^ c) + (uint) K [16] + buff [1];
222 a = (a << 5) | (a >> 27);
223 a += b;
225 d += (((a ^ b) & c) ^ b) + (uint) K [17] + buff [6];
226 d = (d << 9) | (d >> 23);
227 d += a;
229 c += (((d ^ a) & b) ^ a) + (uint) K [18] + buff [11];
230 c = (c << 14) | (c >> 18);
231 c += d;
233 b += (((c ^ d) & a) ^ d) + (uint) K [19] + buff [0];
234 b = (b << 20) | (b >> 12);
235 b += c;
237 a += (((b ^ c) & d) ^ c) + (uint) K [20] + buff [5];
238 a = (a << 5) | (a >> 27);
239 a += b;
241 d += (((a ^ b) & c) ^ b) + (uint) K [21] + buff [10];
242 d = (d << 9) | (d >> 23);
243 d += a;
245 c += (((d ^ a) & b) ^ a) + (uint) K [22] + buff [15];
246 c = (c << 14) | (c >> 18);
247 c += d;
249 b += (((c ^ d) & a) ^ d) + (uint) K [23] + buff [4];
250 b = (b << 20) | (b >> 12);
251 b += c;
253 a += (((b ^ c) & d) ^ c) + (uint) K [24] + buff [9];
254 a = (a << 5) | (a >> 27);
255 a += b;
257 d += (((a ^ b) & c) ^ b) + (uint) K [25] + buff [14];
258 d = (d << 9) | (d >> 23);
259 d += a;
261 c += (((d ^ a) & b) ^ a) + (uint) K [26] + buff [3];
262 c = (c << 14) | (c >> 18);
263 c += d;
265 b += (((c ^ d) & a) ^ d) + (uint) K [27] + buff [8];
266 b = (b << 20) | (b >> 12);
267 b += c;
269 a += (((b ^ c) & d) ^ c) + (uint) K [28] + buff [13];
270 a = (a << 5) | (a >> 27);
271 a += b;
273 d += (((a ^ b) & c) ^ b) + (uint) K [29] + buff [2];
274 d = (d << 9) | (d >> 23);
275 d += a;
277 c += (((d ^ a) & b) ^ a) + (uint) K [30] + buff [7];
278 c = (c << 14) | (c >> 18);
279 c += d;
281 b += (((c ^ d) & a) ^ d) + (uint) K [31] + buff [12];
282 b = (b << 20) | (b >> 12);
283 b += c;
286 // ---- Round 3 --------
288 a += (b ^ c ^ d) + (uint) K [32] + buff [5];
289 a = (a << 4) | (a >> 28);
290 a += b;
292 d += (a ^ b ^ c) + (uint) K [33] + buff [8];
293 d = (d << 11) | (d >> 21);
294 d += a;
296 c += (d ^ a ^ b) + (uint) K [34] + buff [11];
297 c = (c << 16) | (c >> 16);
298 c += d;
300 b += (c ^ d ^ a) + (uint) K [35] + buff [14];
301 b = (b << 23) | (b >> 9);
302 b += c;
304 a += (b ^ c ^ d) + (uint) K [36] + buff [1];
305 a = (a << 4) | (a >> 28);
306 a += b;
308 d += (a ^ b ^ c) + (uint) K [37] + buff [4];
309 d = (d << 11) | (d >> 21);
310 d += a;
312 c += (d ^ a ^ b) + (uint) K [38] + buff [7];
313 c = (c << 16) | (c >> 16);
314 c += d;
316 b += (c ^ d ^ a) + (uint) K [39] + buff [10];
317 b = (b << 23) | (b >> 9);
318 b += c;
320 a += (b ^ c ^ d) + (uint) K [40] + buff [13];
321 a = (a << 4) | (a >> 28);
322 a += b;
324 d += (a ^ b ^ c) + (uint) K [41] + buff [0];
325 d = (d << 11) | (d >> 21);
326 d += a;
328 c += (d ^ a ^ b) + (uint) K [42] + buff [3];
329 c = (c << 16) | (c >> 16);
330 c += d;
332 b += (c ^ d ^ a) + (uint) K [43] + buff [6];
333 b = (b << 23) | (b >> 9);
334 b += c;
336 a += (b ^ c ^ d) + (uint) K [44] + buff [9];
337 a = (a << 4) | (a >> 28);
338 a += b;
340 d += (a ^ b ^ c) + (uint) K [45] + buff [12];
341 d = (d << 11) | (d >> 21);
342 d += a;
344 c += (d ^ a ^ b) + (uint) K [46] + buff [15];
345 c = (c << 16) | (c >> 16);
346 c += d;
348 b += (c ^ d ^ a) + (uint) K [47] + buff [2];
349 b = (b << 23) | (b >> 9);
350 b += c;
353 // ---- Round 4 --------
355 a += (((~d) | b) ^ c) + (uint) K [48] + buff [0];
356 a = (a << 6) | (a >> 26);
357 a += b;
359 d += (((~c) | a) ^ b) + (uint) K [49] + buff [7];
360 d = (d << 10) | (d >> 22);
361 d += a;
363 c += (((~b) | d) ^ a) + (uint) K [50] + buff [14];
364 c = (c << 15) | (c >> 17);
365 c += d;
367 b += (((~a) | c) ^ d) + (uint) K [51] + buff [5];
368 b = (b << 21) | (b >> 11);
369 b += c;
371 a += (((~d) | b) ^ c) + (uint) K [52] + buff [12];
372 a = (a << 6) | (a >> 26);
373 a += b;
375 d += (((~c) | a) ^ b) + (uint) K [53] + buff [3];
376 d = (d << 10) | (d >> 22);
377 d += a;
379 c += (((~b) | d) ^ a) + (uint) K [54] + buff [10];
380 c = (c << 15) | (c >> 17);
381 c += d;
383 b += (((~a) | c) ^ d) + (uint) K [55] + buff [1];
384 b = (b << 21) | (b >> 11);
385 b += c;
387 a += (((~d) | b) ^ c) + (uint) K [56] + buff [8];
388 a = (a << 6) | (a >> 26);
389 a += b;
391 d += (((~c) | a) ^ b) + (uint) K [57] + buff [15];
392 d = (d << 10) | (d >> 22);
393 d += a;
395 c += (((~b) | d) ^ a) + (uint) K [58] + buff [6];
396 c = (c << 15) | (c >> 17);
397 c += d;
399 b += (((~a) | c) ^ d) + (uint) K [59] + buff [13];
400 b = (b << 21) | (b >> 11);
401 b += c;
403 a += (((~d) | b) ^ c) + (uint) K [60] + buff [4];
404 a = (a << 6) | (a >> 26);
405 a += b;
407 d += (((~c) | a) ^ b) + (uint) K [61] + buff [11];
408 d = (d << 10) | (d >> 22);
409 d += a;
411 c += (((~b) | d) ^ a) + (uint) K [62] + buff [2];
412 c = (c << 15) | (c >> 17);
413 c += d;
415 b += (((~a) | c) ^ d) + (uint) K [63] + buff [9];
416 b = (b << 21) | (b >> 11);
417 b += c;
419 _H [0] += a;
420 _H [1] += b;
421 _H [2] += c;
422 _H [3] += d;
425 private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
427 ulong total = count + (ulong)inputCount;
428 int paddingSize = (int)(56 - total % BLOCK_SIZE_BYTES);
430 if (paddingSize < 1)
431 paddingSize += BLOCK_SIZE_BYTES;
433 byte[] fooBuffer = new byte [inputCount+paddingSize+8];
435 for (int i=0; i<inputCount; i++) {
436 fooBuffer[i] = inputBuffer[i+inputOffset];
439 fooBuffer[inputCount] = 0x80;
440 for (int i=inputCount+1; i<inputCount+paddingSize; i++) {
441 fooBuffer[i] = 0x00;
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);
449 if (inputCount+paddingSize+8 == 128) {
450 ProcessBlock(fooBuffer, 64);
454 internal void AddLength (ulong length, byte[] buffer, int position)
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);
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