Added CCM and CCM_8 cipher suites.
[BoarSSL] / Crypto / MD5.cs
1 /*
2 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 using System;
26
27 namespace Crypto {
28
29 /*
30 * MD5 implementation. MD5 is described in RFC 1321.
31 *
32 * WARNING: as a cryptographic hash function, MD5 turned out to be
33 * very weak with regards to collisions. Use with care.
34 */
35
36 public sealed class MD5 : DigestCore {
37
38 const int BLOCK_LEN = 64;
39
40 uint A, B, C, D;
41 byte[] block, saveBlock;
42 int ptr;
43 ulong byteCount;
44
45 /*
46 * Create a new instance. It is ready to process data bytes.
47 */
48 public MD5()
49 {
50 block = new byte[BLOCK_LEN];
51 saveBlock = new byte[BLOCK_LEN];
52 Reset();
53 }
54
55 /* see IDigest */
56 public override string Name {
57 get {
58 return "MD5";
59 }
60 }
61
62 /* see IDigest */
63 public override int DigestSize {
64 get {
65 return 16;
66 }
67 }
68
69 /* see IDigest */
70 public override int BlockSize {
71 get {
72 return 64;
73 }
74 }
75
76 /* see IDigest */
77 public override void Reset()
78 {
79 A = 0x67452301;
80 B = 0xEFCDAB89;
81 C = 0x98BADCFE;
82 D = 0x10325476;
83 byteCount = 0;
84 ptr = 0;
85 }
86
87 /* see IDigest */
88 public override void Update(byte b)
89 {
90 block[ptr ++] = b;
91 byteCount ++;
92 if (ptr == BLOCK_LEN) {
93 ProcessBlock();
94 }
95 }
96
97 /* see IDigest */
98 public override void Update(byte[] buf, int off, int len)
99 {
100 if (len < 0) {
101 throw new ArgumentException("negative chunk length");
102 }
103 byteCount += (ulong)len;
104 while (len > 0) {
105 int clen = Math.Min(len, BLOCK_LEN - ptr);
106 Array.Copy(buf, off, block, ptr, clen);
107 off += clen;
108 len -= clen;
109 ptr += clen;
110 if (ptr == BLOCK_LEN) {
111 ProcessBlock();
112 }
113 }
114 }
115
116 /* see IDigest */
117 public override void DoPartial(byte[] outBuf, int off)
118 {
119 /*
120 * Save current state.
121 */
122 uint saveA = A;
123 uint saveB = B;
124 uint saveC = C;
125 uint saveD = D;
126 int savePtr = ptr;
127 Array.Copy(block, 0, saveBlock, 0, savePtr);
128
129 /*
130 * Add padding. This may involve processing an extra block.
131 */
132 block[ptr ++] = 0x80;
133 if (ptr > BLOCK_LEN - 8) {
134 for (int j = ptr; j < BLOCK_LEN; j ++) {
135 block[j] = 0;
136 }
137 ProcessBlock();
138 }
139 for (int j = ptr; j < (BLOCK_LEN - 8); j ++) {
140 block[j] = 0;
141 }
142 ulong x = byteCount << 3;
143 Enc32le((uint)x, block, BLOCK_LEN - 8);
144 Enc32le((uint)(x >> 32), block, BLOCK_LEN - 4);
145
146 /*
147 * Process final block and encode result.
148 */
149 ProcessBlock();
150 Enc32le(A, outBuf, off);
151 Enc32le(B, outBuf, off + 4);
152 Enc32le(C, outBuf, off + 8);
153 Enc32le(D, outBuf, off + 12);
154
155 /*
156 * Restore current state.
157 */
158 Array.Copy(saveBlock, 0, block, 0, savePtr);
159 A = saveA;
160 B = saveB;
161 C = saveC;
162 D = saveD;
163 ptr = savePtr;
164 }
165
166 /* see IDigest */
167 public override IDigest Dup()
168 {
169 MD5 h = new MD5();
170 h.A = A;
171 h.B = B;
172 h.C = C;
173 h.D = D;
174 h.ptr = ptr;
175 h.byteCount = byteCount;
176 Array.Copy(block, 0, h.block, 0, ptr);
177 return h;
178 }
179
180 /* see IDigest */
181 public override void CurrentState(byte[] outBuf, int off)
182 {
183 Enc32le(A, outBuf, off);
184 Enc32le(B, outBuf, off + 4);
185 Enc32le(C, outBuf, off + 8);
186 Enc32le(D, outBuf, off + 12);
187 }
188
189 void ProcessBlock()
190 {
191 /*
192 * Decode input block (sixteen 32-bit words).
193 */
194 uint x0 = Dec32le(block, 0);
195 uint x1 = Dec32le(block, 4);
196 uint x2 = Dec32le(block, 8);
197 uint x3 = Dec32le(block, 12);
198 uint x4 = Dec32le(block, 16);
199 uint x5 = Dec32le(block, 20);
200 uint x6 = Dec32le(block, 24);
201 uint x7 = Dec32le(block, 28);
202 uint x8 = Dec32le(block, 32);
203 uint x9 = Dec32le(block, 36);
204 uint xA = Dec32le(block, 40);
205 uint xB = Dec32le(block, 44);
206 uint xC = Dec32le(block, 48);
207 uint xD = Dec32le(block, 52);
208 uint xE = Dec32le(block, 56);
209 uint xF = Dec32le(block, 60);
210
211 /*
212 * Read state words.
213 */
214 uint wa = A;
215 uint wb = B;
216 uint wc = C;
217 uint wd = D;
218 uint tmp;
219
220 /*
221 * Rounds 0 to 15.
222 */
223 tmp = wa + (wd ^ (wb & (wc ^ wd))) + x0 + 0xD76AA478;
224 wa = wb + ((tmp << 7) | (tmp >> 25));
225 tmp = wd + (wc ^ (wa & (wb ^ wc))) + x1 + 0xE8C7B756;
226 wd = wa + ((tmp << 12) | (tmp >> 20));
227 tmp = wc + (wb ^ (wd & (wa ^ wb))) + x2 + 0x242070DB;
228 wc = wd + ((tmp << 17) | (tmp >> 15));
229 tmp = wb + (wa ^ (wc & (wd ^ wa))) + x3 + 0xC1BDCEEE;
230 wb = wc + ((tmp << 22) | (tmp >> 10));
231 tmp = wa + (wd ^ (wb & (wc ^ wd))) + x4 + 0xF57C0FAF;
232 wa = wb + ((tmp << 7) | (tmp >> 25));
233 tmp = wd + (wc ^ (wa & (wb ^ wc))) + x5 + 0x4787C62A;
234 wd = wa + ((tmp << 12) | (tmp >> 20));
235 tmp = wc + (wb ^ (wd & (wa ^ wb))) + x6 + 0xA8304613;
236 wc = wd + ((tmp << 17) | (tmp >> 15));
237 tmp = wb + (wa ^ (wc & (wd ^ wa))) + x7 + 0xFD469501;
238 wb = wc + ((tmp << 22) | (tmp >> 10));
239 tmp = wa + (wd ^ (wb & (wc ^ wd))) + x8 + 0x698098D8;
240 wa = wb + ((tmp << 7) | (tmp >> 25));
241 tmp = wd + (wc ^ (wa & (wb ^ wc))) + x9 + 0x8B44F7AF;
242 wd = wa + ((tmp << 12) | (tmp >> 20));
243 tmp = wc + (wb ^ (wd & (wa ^ wb))) + xA + 0xFFFF5BB1;
244 wc = wd + ((tmp << 17) | (tmp >> 15));
245 tmp = wb + (wa ^ (wc & (wd ^ wa))) + xB + 0x895CD7BE;
246 wb = wc + ((tmp << 22) | (tmp >> 10));
247 tmp = wa + (wd ^ (wb & (wc ^ wd))) + xC + 0x6B901122;
248 wa = wb + ((tmp << 7) | (tmp >> 25));
249 tmp = wd + (wc ^ (wa & (wb ^ wc))) + xD + 0xFD987193;
250 wd = wa + ((tmp << 12) | (tmp >> 20));
251 tmp = wc + (wb ^ (wd & (wa ^ wb))) + xE + 0xA679438E;
252 wc = wd + ((tmp << 17) | (tmp >> 15));
253 tmp = wb + (wa ^ (wc & (wd ^ wa))) + xF + 0x49B40821;
254 wb = wc + ((tmp << 22) | (tmp >> 10));
255
256 /*
257 * Rounds 16 to 31.
258 */
259 tmp = wa + (wc ^ (wd & (wb ^ wc))) + x1 + 0xF61E2562;
260 wa = wb + ((tmp << 5) | (tmp >> 27));
261 tmp = wd + (wb ^ (wc & (wa ^ wb))) + x6 + 0xC040B340;
262 wd = wa + ((tmp << 9) | (tmp >> 23));
263 tmp = wc + (wa ^ (wb & (wd ^ wa))) + xB + 0x265E5A51;
264 wc = wd + ((tmp << 14) | (tmp >> 18));
265 tmp = wb + (wd ^ (wa & (wc ^ wd))) + x0 + 0xE9B6C7AA;
266 wb = wc + ((tmp << 20) | (tmp >> 12));
267 tmp = wa + (wc ^ (wd & (wb ^ wc))) + x5 + 0xD62F105D;
268 wa = wb + ((tmp << 5) | (tmp >> 27));
269 tmp = wd + (wb ^ (wc & (wa ^ wb))) + xA + 0x02441453;
270 wd = wa + ((tmp << 9) | (tmp >> 23));
271 tmp = wc + (wa ^ (wb & (wd ^ wa))) + xF + 0xD8A1E681;
272 wc = wd + ((tmp << 14) | (tmp >> 18));
273 tmp = wb + (wd ^ (wa & (wc ^ wd))) + x4 + 0xE7D3FBC8;
274 wb = wc + ((tmp << 20) | (tmp >> 12));
275 tmp = wa + (wc ^ (wd & (wb ^ wc))) + x9 + 0x21E1CDE6;
276 wa = wb + ((tmp << 5) | (tmp >> 27));
277 tmp = wd + (wb ^ (wc & (wa ^ wb))) + xE + 0xC33707D6;
278 wd = wa + ((tmp << 9) | (tmp >> 23));
279 tmp = wc + (wa ^ (wb & (wd ^ wa))) + x3 + 0xF4D50D87;
280 wc = wd + ((tmp << 14) | (tmp >> 18));
281 tmp = wb + (wd ^ (wa & (wc ^ wd))) + x8 + 0x455A14ED;
282 wb = wc + ((tmp << 20) | (tmp >> 12));
283 tmp = wa + (wc ^ (wd & (wb ^ wc))) + xD + 0xA9E3E905;
284 wa = wb + ((tmp << 5) | (tmp >> 27));
285 tmp = wd + (wb ^ (wc & (wa ^ wb))) + x2 + 0xFCEFA3F8;
286 wd = wa + ((tmp << 9) | (tmp >> 23));
287 tmp = wc + (wa ^ (wb & (wd ^ wa))) + x7 + 0x676F02D9;
288 wc = wd + ((tmp << 14) | (tmp >> 18));
289 tmp = wb + (wd ^ (wa & (wc ^ wd))) + xC + 0x8D2A4C8A;
290 wb = wc + ((tmp << 20) | (tmp >> 12));
291
292 /*
293 * Rounds 32 to 47.
294 */
295 tmp = wa + (wb ^ wc ^ wd) + x5 + 0xFFFA3942;
296 wa = wb + ((tmp << 4) | (tmp >> 28));
297 tmp = wd + (wa ^ wb ^ wc) + x8 + 0x8771F681;
298 wd = wa + ((tmp << 11) | (tmp >> 21));
299 tmp = wc + (wd ^ wa ^ wb) + xB + 0x6D9D6122;
300 wc = wd + ((tmp << 16) | (tmp >> 16));
301 tmp = wb + (wc ^ wd ^ wa) + xE + 0xFDE5380C;
302 wb = wc + ((tmp << 23) | (tmp >> 9));
303 tmp = wa + (wb ^ wc ^ wd) + x1 + 0xA4BEEA44;
304 wa = wb + ((tmp << 4) | (tmp >> 28));
305 tmp = wd + (wa ^ wb ^ wc) + x4 + 0x4BDECFA9;
306 wd = wa + ((tmp << 11) | (tmp >> 21));
307 tmp = wc + (wd ^ wa ^ wb) + x7 + 0xF6BB4B60;
308 wc = wd + ((tmp << 16) | (tmp >> 16));
309 tmp = wb + (wc ^ wd ^ wa) + xA + 0xBEBFBC70;
310 wb = wc + ((tmp << 23) | (tmp >> 9));
311 tmp = wa + (wb ^ wc ^ wd) + xD + 0x289B7EC6;
312 wa = wb + ((tmp << 4) | (tmp >> 28));
313 tmp = wd + (wa ^ wb ^ wc) + x0 + 0xEAA127FA;
314 wd = wa + ((tmp << 11) | (tmp >> 21));
315 tmp = wc + (wd ^ wa ^ wb) + x3 + 0xD4EF3085;
316 wc = wd + ((tmp << 16) | (tmp >> 16));
317 tmp = wb + (wc ^ wd ^ wa) + x6 + 0x04881D05;
318 wb = wc + ((tmp << 23) | (tmp >> 9));
319 tmp = wa + (wb ^ wc ^ wd) + x9 + 0xD9D4D039;
320 wa = wb + ((tmp << 4) | (tmp >> 28));
321 tmp = wd + (wa ^ wb ^ wc) + xC + 0xE6DB99E5;
322 wd = wa + ((tmp << 11) | (tmp >> 21));
323 tmp = wc + (wd ^ wa ^ wb) + xF + 0x1FA27CF8;
324 wc = wd + ((tmp << 16) | (tmp >> 16));
325 tmp = wb + (wc ^ wd ^ wa) + x2 + 0xC4AC5665;
326 wb = wc + ((tmp << 23) | (tmp >> 9));
327
328 /*
329 * Rounds 48 to 63.
330 */
331 tmp = wa + (wc ^ (wb | ~wd)) + x0 + 0xF4292244;
332 wa = wb + ((tmp << 6) | (tmp >> 26));
333 tmp = wd + (wb ^ (wa | ~wc)) + x7 + 0x432AFF97;
334 wd = wa + ((tmp << 10) | (tmp >> 22));
335 tmp = wc + (wa ^ (wd | ~wb)) + xE + 0xAB9423A7;
336 wc = wd + ((tmp << 15) | (tmp >> 17));
337 tmp = wb + (wd ^ (wc | ~wa)) + x5 + 0xFC93A039;
338 wb = wc + ((tmp << 21) | (tmp >> 11));
339 tmp = wa + (wc ^ (wb | ~wd)) + xC + 0x655B59C3;
340 wa = wb + ((tmp << 6) | (tmp >> 26));
341 tmp = wd + (wb ^ (wa | ~wc)) + x3 + 0x8F0CCC92;
342 wd = wa + ((tmp << 10) | (tmp >> 22));
343 tmp = wc + (wa ^ (wd | ~wb)) + xA + 0xFFEFF47D;
344 wc = wd + ((tmp << 15) | (tmp >> 17));
345 tmp = wb + (wd ^ (wc | ~wa)) + x1 + 0x85845DD1;
346 wb = wc + ((tmp << 21) | (tmp >> 11));
347 tmp = wa + (wc ^ (wb | ~wd)) + x8 + 0x6FA87E4F;
348 wa = wb + ((tmp << 6) | (tmp >> 26));
349 tmp = wd + (wb ^ (wa | ~wc)) + xF + 0xFE2CE6E0;
350 wd = wa + ((tmp << 10) | (tmp >> 22));
351 tmp = wc + (wa ^ (wd | ~wb)) + x6 + 0xA3014314;
352 wc = wd + ((tmp << 15) | (tmp >> 17));
353 tmp = wb + (wd ^ (wc | ~wa)) + xD + 0x4E0811A1;
354 wb = wc + ((tmp << 21) | (tmp >> 11));
355 tmp = wa + (wc ^ (wb | ~wd)) + x4 + 0xF7537E82;
356 wa = wb + ((tmp << 6) | (tmp >> 26));
357 tmp = wd + (wb ^ (wa | ~wc)) + xB + 0xBD3AF235;
358 wd = wa + ((tmp << 10) | (tmp >> 22));
359 tmp = wc + (wa ^ (wd | ~wb)) + x2 + 0x2AD7D2BB;
360 wc = wd + ((tmp << 15) | (tmp >> 17));
361 tmp = wb + (wd ^ (wc | ~wa)) + x9 + 0xEB86D391;
362 wb = wc + ((tmp << 21) | (tmp >> 11));
363
364 /*
365 * Update state words and reset block pointer.
366 */
367 A += wa;
368 B += wb;
369 C += wc;
370 D += wd;
371 ptr = 0;
372 }
373
374 static uint Dec32le(byte[] buf, int off)
375 {
376 return (uint)buf[off]
377 | ((uint)buf[off + 1] << 8)
378 | ((uint)buf[off + 2] << 16)
379 | ((uint)buf[off + 3] << 24);
380 }
381
382 static void Enc32le(uint x, byte[] buf, int off)
383 {
384 buf[off] = (byte)x;
385 buf[off + 1] = (byte)(x >> 8);
386 buf[off + 2] = (byte)(x >> 16);
387 buf[off + 3] = (byte)(x >> 24);
388 }
389 }
390
391 }