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