1 /*
2 Copyright (C) 2014-2017,2018 John E. Davis
3
4 This file is part of the S-Lang Library.
5
6 The S-Lang Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 The S-Lang Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA.
20 */
21
22 #include "config.h"
23 #include <string.h>
24 #include <slang.h>
25
26 #include "_slint.h"
27
28 #define MD5_BUFSIZE 64
29 #define MD5_DIGEST_LEN 16
30 #define CHKSUM_TYPE_PRIVATE_FIELDS \
31 _pSLuint32_Type abcd[4]; \
32 _pSLuint32_Type num_bits[2]; /* 64 bit representation */ \
33 unsigned int num_buffered; \
34 unsigned char buf[MD5_BUFSIZE];
35 #include "chksum.h"
36
37 /* 8 bit bytes assumed in what follows. The algorithm is based upon
38 * section 3 of RFC 1321.
39 */
40
41 /*
42 3.1 Step 1. Append Padding Bits
43
44 The message is "padded" (extended) so that its length (in bits) is
45 congruent to 448, modulo 512. That is, the message is extended so
46 that it is just 64 bits shy of being a multiple of 512 bits long.
47 Padding is always performed, even if the length of the message is
48 already congruent to 448, modulo 512.
49 */
50
compute_pad_length(unsigned int len)51 static unsigned int compute_pad_length (unsigned int len)
52 {
53 unsigned int mod64 = len % 64;
54 unsigned int dlen;
55
56 if (mod64 < 56)
57 dlen = 56 - mod64;
58 else
59 dlen = 120 - mod64;
60
61 return dlen;
62 }
63
64 /* Padding is performed as follows: a single "1" bit is appended to the */
65 /* message, and then "0" bits are appended so that the length in bits of */
66 /* the padded message becomes congruent to 448, modulo 512. In all, at */
67 /* least one bit and at most 512 bits are appended. */
68 static unsigned char Pad_Bytes[64] =
69 {
70 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
78 };
79
80 /*
81 3.2 Step 2. Append Length
82
83 A 64-bit representation of b (the length of the message before the
84 padding bits were added) is appended to the result of the previous
85 step. In the unlikely event that b is greater than 2^64, then only
86 the low-order 64 bits of b are used. (These bits are appended as two
87 32-bit words and appended low-order word first in accordance with the
88 previous conventions.)
89
90 At this point the resulting message (after padding with bits and with
91 b) has a length that is an exact multiple of 512 bits. Equivalently,
92 this message has a length that is an exact multiple of 16 (32-bit)
93 words. Let M[0 ... N-1] denote the words of the resulting message,
94 where N is a multiple of 16.
95 */
96
97 /*
98 3.3 Step 3. Initialize MD Buffer
99
100 A four-word buffer (A,B,C,D) is used to compute the message digest.
101 Here each of A, B, C, D is a 32-bit register. These registers are
102 initialized to the following values in hexadecimal, low-order bytes
103 first):
104
105 word A: 01 23 45 67
106 word B: 89 ab cd ef
107 word C: fe dc ba 98
108 word D: 76 54 32 10
109 */
110
init_md5_buffer(_pSLuint32_Type buffer[4])111 static void init_md5_buffer (_pSLuint32_Type buffer[4])
112 {
113 buffer[0] = 0x67452301;
114 buffer[1] = 0xEFCDAB89;
115 buffer[2] = 0x98BADCFE;
116 buffer[3] = 0x10325476;
117 }
118
119 /*
120 3.4 Step 4. Process Message in 16-Word Blocks
121
122 We first define four auxiliary functions that each take as input
123 three 32-bit words and produce as output one 32-bit word.
124
125 F(X,Y,Z) = XY v not(X) Z
126 G(X,Y,Z) = XZ v Y not(Z)
127 H(X,Y,Z) = X xor Y xor Z
128 I(X,Y,Z) = Y xor (X v not(Z))
129 */
130
131 #define MD5_F_OP(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z)))
132 #define MD5_G_OP(X,Y,Z) (((X)&(Z)) | ((Y)&(~(Z))))
133 #define MD5_H_OP(X,Y,Z) ((X)^(Y)^(Z))
134 #define MD5_I_OP(X,Y,Z) ((Y)^((X)|(~(Z))))
135
136 /* The algorithm works on blocks that consist of 16 32bit ints */
process_block(_pSLuint32_Type block[16],_pSLuint32_Type abcd[4])137 static void process_block (_pSLuint32_Type block[16], _pSLuint32_Type abcd[4])
138 {
139 _pSLuint32_Type a = abcd[0], b = abcd[1], c = abcd[2], d = abcd[3];
140
141 #define MD5_ROTATE(a,n) (((a)<<(n)) | ((a)>>(32-(n))))
142
143 #define MD5_ROUND1_OP(A,B,C,D,k,s,t) \
144 A += MD5_F_OP(B,C,D) + block[k] + t;\
145 A = B + MD5_ROTATE(A,s);
146
147 #define MD5_ROUND2_OP(A,B,C,D,k,s,t) \
148 A += MD5_G_OP(B,C,D) + block[k] + t;\
149 A = B + MD5_ROTATE(A,s);
150
151 #define MD5_ROUND3_OP(A,B,C,D,k,s,t) \
152 A += MD5_H_OP(B,C,D) + block[k] + t;\
153 A = B + MD5_ROTATE(A,s);
154
155 #define MD5_ROUND4_OP(A,B,C,D,k,s,t) \
156 A += MD5_I_OP(B,C,D) + block[k] + t;\
157 A = B + MD5_ROTATE(A,s);
158
159 MD5_ROUND1_OP(a,b,c,d,0,7,0xD76AA478);
160 MD5_ROUND1_OP(d,a,b,c,1,12,0xE8C7B756);
161 MD5_ROUND1_OP(c,d,a,b,2,17,0x242070DB);
162 MD5_ROUND1_OP(b,c,d,a,3,22,0xC1BDCEEE);
163 MD5_ROUND1_OP(a,b,c,d,4,7,0xF57C0FAF);
164 MD5_ROUND1_OP(d,a,b,c,5,12,0x4787C62A);
165 MD5_ROUND1_OP(c,d,a,b,6,17,0xA8304613);
166 MD5_ROUND1_OP(b,c,d,a,7,22,0xFD469501);
167 MD5_ROUND1_OP(a,b,c,d,8,7,0x698098D8);
168 MD5_ROUND1_OP(d,a,b,c,9,12,0x8B44F7AF);
169 MD5_ROUND1_OP(c,d,a,b,10,17,0xFFFF5BB1);
170 MD5_ROUND1_OP(b,c,d,a,11,22,0x895CD7BE);
171 MD5_ROUND1_OP(a,b,c,d,12,7,0x6B901122);
172 MD5_ROUND1_OP(d,a,b,c,13,12,0xFD987193);
173 MD5_ROUND1_OP(c,d,a,b,14,17,0xA679438E);
174 MD5_ROUND1_OP(b,c,d,a,15,22,0x49B40821);
175
176 MD5_ROUND2_OP(a,b,c,d,1,5,0xF61E2562);
177 MD5_ROUND2_OP(d,a,b,c,6,9,0xC040B340);
178 MD5_ROUND2_OP(c,d,a,b,11,14,0x265E5A51);
179 MD5_ROUND2_OP(b,c,d,a,0,20,0xE9B6C7AA);
180 MD5_ROUND2_OP(a,b,c,d,5,5,0xD62F105D);
181 MD5_ROUND2_OP(d,a,b,c,10,9,0x02441453);
182 MD5_ROUND2_OP(c,d,a,b,15,14,0xD8A1E681);
183 MD5_ROUND2_OP(b,c,d,a,4,20,0xE7D3FBC8);
184 MD5_ROUND2_OP(a,b,c,d,9,5,0x21E1CDE6);
185 MD5_ROUND2_OP(d,a,b,c,14,9,0xC33707D6);
186 MD5_ROUND2_OP(c,d,a,b,3,14,0xF4D50D87);
187 MD5_ROUND2_OP(b,c,d,a,8,20,0x455A14ED);
188 MD5_ROUND2_OP(a,b,c,d,13,5,0xA9E3E905);
189 MD5_ROUND2_OP(d,a,b,c,2,9,0xFCEFA3F8);
190 MD5_ROUND2_OP(c,d,a,b,7,14,0x676F02D9);
191 MD5_ROUND2_OP(b,c,d,a,12,20,0x8D2A4C8A);
192
193 MD5_ROUND3_OP(a,b,c,d,5,4,0xFFFA3942);
194 MD5_ROUND3_OP(d,a,b,c,8,11,0x8771F681);
195 MD5_ROUND3_OP(c,d,a,b,11,16,0x6D9D6122);
196 MD5_ROUND3_OP(b,c,d,a,14,23,0xFDE5380C);
197 MD5_ROUND3_OP(a,b,c,d,1,4,0xA4BEEA44);
198 MD5_ROUND3_OP(d,a,b,c,4,11,0x4BDECFA9);
199 MD5_ROUND3_OP(c,d,a,b,7,16,0xF6BB4B60);
200 MD5_ROUND3_OP(b,c,d,a,10,23,0xBEBFBC70);
201 MD5_ROUND3_OP(a,b,c,d,13,4,0x289B7EC6);
202 MD5_ROUND3_OP(d,a,b,c,0,11,0xEAA127FA);
203 MD5_ROUND3_OP(c,d,a,b,3,16,0xD4EF3085);
204 MD5_ROUND3_OP(b,c,d,a,6,23,0x04881D05);
205 MD5_ROUND3_OP(a,b,c,d,9,4,0xD9D4D039);
206 MD5_ROUND3_OP(d,a,b,c,12,11,0xE6DB99E5);
207 MD5_ROUND3_OP(c,d,a,b,15,16,0x1FA27CF8);
208 MD5_ROUND3_OP(b,c,d,a,2,23,0xC4AC5665);
209
210 MD5_ROUND4_OP(a,b,c,d,0,6,0xF4292244);
211 MD5_ROUND4_OP(d,a,b,c,7,10,0x432AFF97);
212 MD5_ROUND4_OP(c,d,a,b,14,15,0xAB9423A7);
213 MD5_ROUND4_OP(b,c,d,a,5,21,0xFC93A039);
214 MD5_ROUND4_OP(a,b,c,d,12,6,0x655B59C3);
215 MD5_ROUND4_OP(d,a,b,c,3,10,0x8F0CCC92);
216 MD5_ROUND4_OP(c,d,a,b,10,15,0xFFEFF47D);
217 MD5_ROUND4_OP(b,c,d,a,1,21,0x85845DD1);
218 MD5_ROUND4_OP(a,b,c,d,8,6,0x6FA87E4F);
219 MD5_ROUND4_OP(d,a,b,c,15,10,0xFE2CE6E0);
220 MD5_ROUND4_OP(c,d,a,b,6,15,0xA3014314);
221 MD5_ROUND4_OP(b,c,d,a,13,21,0x4E0811A1);
222 MD5_ROUND4_OP(a,b,c,d,4,6,0xF7537E82);
223 MD5_ROUND4_OP(d,a,b,c,11,10,0xBD3AF235);
224 MD5_ROUND4_OP(c,d,a,b,2,15,0x2AD7D2BB);
225 MD5_ROUND4_OP(b,c,d,a,9,21,0xEB86D391);
226
227 abcd[0] += a;
228 abcd[1] += b;
229 abcd[2] += c;
230 abcd[3] += d;
231 }
232
233 /* Note: Little Endian is used */
uint32_to_uchar(_pSLuint32_Type * u,unsigned int num,unsigned char * buf)234 static void uint32_to_uchar (_pSLuint32_Type *u, unsigned int num, unsigned char *buf)
235 {
236 unsigned short t = 0xFF;
237 unsigned int i;
238
239 if (*(unsigned char *)&t == 0xFF)
240 {
241 memcpy ((char *)buf, (char *)u, num*4);
242 return;
243 }
244
245 for (i = 0; i < num; i++)
246 {
247 _pSLuint32_Type x = u[i];
248 buf[0] = (unsigned char) (x & 0xFF);
249 buf[1] = (unsigned char) ((x>>8) & 0xFF);
250 buf[2] = (unsigned char) ((x>>16) & 0xFF);
251 buf[3] = (unsigned char) ((x>>24) & 0xFF);
252 buf += 4;
253 }
254 }
255
uchar_to_uint32(unsigned char * buf,unsigned int len,_pSLuint32_Type * u)256 static void uchar_to_uint32 (unsigned char *buf, unsigned int len, _pSLuint32_Type *u)
257 {
258 unsigned short x = 0xFF;
259 unsigned char *bufmax;
260
261 if (*(unsigned char *)&x == 0xFF)
262 {
263 memcpy ((char *)u, buf, len);
264 return;
265 }
266
267 bufmax = buf + len;
268 while (buf < bufmax)
269 {
270 *u++ = (((_pSLuint32_Type)buf[0]) | ((_pSLuint32_Type)buf[1]<<8)
271 | ((_pSLuint32_Type)buf[2]<<16) | ((_pSLuint32_Type)buf[3]<<24));
272 buf += 4;
273 }
274 }
275
process_64_byte_block(unsigned char * buf,_pSLuint32_Type abcd[4])276 static void process_64_byte_block (unsigned char *buf, _pSLuint32_Type abcd[4])
277 {
278 _pSLuint32_Type block[16];
279
280 uchar_to_uint32 (buf, 64, block);
281 process_block (block, abcd);
282 }
283
update_num_bits(SLChksum_Type * md5,unsigned int dnum_bits)284 static void update_num_bits (SLChksum_Type *md5, unsigned int dnum_bits)
285 {
286 _pSLuint32_Type d, lo, hi;
287
288 d = (_pSLuint32_Type)dnum_bits << 3;
289 lo = md5->num_bits[0];
290 hi = md5->num_bits[1];
291
292 d += lo;
293 if (d < lo)
294 hi++; /* overflow */
295 hi += (_pSLuint32_Type)dnum_bits >> 29;
296 lo = d;
297
298 md5->num_bits[0] = lo;
299 md5->num_bits[1] = hi;
300 }
301
md5_accumulate(SLChksum_Type * md5,unsigned char * buf,unsigned int buflen)302 static int md5_accumulate (SLChksum_Type *md5, unsigned char *buf, unsigned int buflen)
303 {
304 unsigned int num_buffered;
305 unsigned char *bufmax;
306
307 if ((md5 == NULL) || (buf == NULL))
308 return -1;
309
310 update_num_bits (md5, buflen);
311
312 num_buffered = md5->num_buffered;
313
314 if (num_buffered)
315 {
316 unsigned int dlen = MD5_BUFSIZE - md5->num_buffered;
317
318 if (buflen < dlen)
319 dlen = buflen;
320
321 memcpy (md5->buf+num_buffered, buf, dlen);
322 num_buffered += dlen;
323 buflen -= dlen;
324 buf += dlen;
325
326 if (num_buffered < MD5_BUFSIZE)
327 {
328 md5->num_buffered = num_buffered;
329 return 0;
330 }
331
332 process_64_byte_block (md5->buf, md5->abcd);
333 num_buffered = 0;
334 }
335
336 num_buffered = buflen % MD5_BUFSIZE;
337 bufmax = buf + (buflen - num_buffered);
338 while (buf < bufmax)
339 {
340 process_64_byte_block (buf, md5->abcd);
341 buf += MD5_BUFSIZE;
342 }
343
344 if (num_buffered)
345 memcpy (md5->buf, bufmax, num_buffered);
346
347 md5->num_buffered = num_buffered;
348
349 return 0;
350 }
351
md5_close(SLChksum_Type * md5,unsigned char * digest)352 static int md5_close (SLChksum_Type *md5, unsigned char *digest)
353 {
354 unsigned char num_bits_buf[8];
355
356 if (md5 == NULL)
357 return -1;
358
359 if (digest != NULL)
360 {
361 /* Handle num bits before padding */
362 uint32_to_uchar (md5->num_bits, 2, num_bits_buf);
363
364 /* Add pad and num_bits bytes */
365 (void) md5_accumulate (md5, Pad_Bytes, compute_pad_length (md5->num_buffered));
366 (void) md5_accumulate (md5, num_bits_buf, 8);
367 uint32_to_uchar (md5->abcd, 4, digest);
368 }
369
370 SLfree ((char *)md5);
371 return 0;
372 }
373
_pSLchksum_md5_new(char * name)374 SLChksum_Type *_pSLchksum_md5_new (char *name)
375 {
376 SLChksum_Type *md5;
377 (void) name;
378
379 if (NULL == (md5 = (SLChksum_Type *) SLmalloc (sizeof(SLChksum_Type))))
380 return NULL;
381 memset ((char *)md5, 0, sizeof (SLChksum_Type));
382 md5->accumulate = md5_accumulate;
383 md5->close = md5_close;
384 md5->digest_len = MD5_DIGEST_LEN;
385 init_md5_buffer (md5->abcd);
386
387 return md5;
388 }
389
390 #if 0
391 int main ()
392 {
393 SLChksum_Type *md5;
394 unsigned int i;
395 unsigned char buf[1024];
396 unsigned int len;
397 unsigned char *digest;
398
399 if (NULL == (md5 = _pSLchksum_md5_new ("md5")))
400 return 1;
401
402 while (0 != (len = fread (buf, 1, sizeof (buf), stdin)))
403 (void) md5->accumulate (md5, buf, len);
404
405 if (NULL == (digest = (unsigned char *)SLmalloc (md5->digest_len)))
406 return 1;
407
408 md5->close (md5, digest);
409
410 for (i = 0; i < 16; i++)
411 fprintf (stdout, "%02x", digest[i]);
412 fputs ("\n", stdout);
413 SLfree ((char *)digest);
414
415 return 0;
416 }
417 #endif
418
419