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 #include "config.h"
22 #include <string.h>
23 #include <limits.h>
24 #include <slang.h>
25 
26 #include "_slint.h"
27 
28 #define SHA1_BUFSIZE	64
29 #define SHA1_DIGEST_LEN	20
30 #define CHKSUM_TYPE_PRIVATE_FIELDS \
31    _pSLuint32_Type h[5]; \
32    _pSLuint32_Type num_bits[2];		       /* 64 bit representation */ \
33    unsigned int num_buffered; \
34    unsigned char buf[SHA1_BUFSIZE];
35 
36 #include "chksum.h"
37 
38 /* 8 bit bytes assumed in what follows.  The algorithm is based upon
39  * <http://www.itl.nist.gov/fipspubs/fip180-1.htm>
40  *
41  * The algorithm there resembles that of RFC1321, which defines the
42  * MD5 checksum.  The notes that follow have been adapted from my
43  * md5sum code.
44  */
45 
46 /*
47    The message is "padded" (extended) so that its length (in bits) is
48    congruent to 448, modulo 512. That is, the message is extended so
49    that it is just 64 bits shy of being a multiple of 512 bits long.
50    Padding is always performed, even if the length of the message is
51    already congruent to 448, modulo 512.
52 */
compute_pad_length(unsigned int len)53 static unsigned int compute_pad_length (unsigned int len)
54 {
55    unsigned int mod64 = len % 64;
56    unsigned int dlen;
57 
58    if (mod64 < 56)
59      dlen = 56 - mod64;
60    else
61      dlen = 120 - mod64;
62 
63    return dlen;
64 }
65 
66 /* Padding is performed as follows: a single "1" bit is appended to the
67  *  message, and then "0" bits are appended so that the length in bits
68  *  of the padded message becomes congruent to 448, modulo 512. In
69  *  all, at least one bit and at most 512 bits are appended.
70  *
71  * A 64-bit representation of b (the length of the message before the
72  * padding bits were added) is appended to the result of the previous
73  * step. In the unlikely event that b is greater than 2^64, then only
74  * the low-order 64 bits of b are used. (These bits are appended as two
75  * 32-bit words and appended low-order word first in accordance with the
76  * previous conventions.)
77  *
78  * At this point the resulting message (after padding with bits and with
79  * b) has a length that is an exact multiple of 512 bits. Equivalently,
80  * this message has a length that is an exact multiple of 16 (32-bit)
81  * words. Let M[0 ... N-1] denote the words of the resulting message,
82  * where N is a multiple of 16.
83  */
84 static unsigned char Pad_Bytes[64] =
85 {
86    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
94 };
95 
96 /*
97  * The message digest is computed using the final padded message. The
98  * computation uses two buffers, each consisting of five 32-bit
99  * words, and a sequence of eighty 32-bit words. The words of the
100  * first 5-word buffer are labeled A,B,C,D,E. The words of the second
101  * 5-word buffer are labeled H0, H1, H2, H3, H4. The words of the
102  * 80-word sequence are labeled W0, W1,..., W79. A single word buffer
103  * TEMP is also employed.
104  */
105 
106 /* Initialization
107  *
108  * A four-word buffer (A,B,C,D) is used to compute the message digest.
109  * Here each of A, B, C, D is a 32-bit register. These registers are
110  * initialized to the following values in hexadecimal.
111  */
112 
overflow_add(_pSLuint32_Type a,_pSLuint32_Type b,_pSLuint32_Type * c)113 static _pSLuint32_Type overflow_add (_pSLuint32_Type a, _pSLuint32_Type b, _pSLuint32_Type *c)
114 {
115    _pSLuint32_Type b1 = UINT_MAX - b;
116    if (a <= b1)
117      {
118 	*c = 0;
119 	return a+b;
120      }
121    *c = 1;
122    return (a - b1) - 1;
123 }
124 
update_num_bits(SLChksum_Type * sha1,unsigned int dnum_bits)125 static int update_num_bits (SLChksum_Type *sha1, unsigned int dnum_bits)
126 {
127    _pSLuint32_Type lo, hi, c, d;
128 
129    d = (_pSLuint32_Type)dnum_bits << 3;
130    hi = sha1->num_bits[0];
131    lo = sha1->num_bits[1];
132 
133    lo = overflow_add (lo, d, &c);
134    if (c)
135      {
136 	hi = overflow_add (hi, c, &c);
137 	if (c)
138 	  return -1;
139      }
140    hi = overflow_add (hi, dnum_bits >> 29, &c);
141    if (c)
142      return -1;
143 
144    sha1->num_bits[0] = hi;
145    sha1->num_bits[1] = lo;
146    return 0;
147 }
148 
149 #define F_00_19(B,C,D) (((B) & (C)) | (~(B) & (D)))
150 #define F_20_39(B,C,D) ((B)^(C)^(D))
151 #define F_40_59(B,C,D) (((B)&(C)) | ((B)&(D)) | ((C)&(D)))
152 #define F_60_79(B,C,D) ((B)^(C)^(D))
153 #define K_00_19 0x5A827999
154 #define K_20_39 0x6ED9EBA1
155 #define K_40_59 0x8F1BBCDC
156 #define K_60_79 0xCA62C1D6
157 #define CSHIFT(n,X) (((X) << (n)) | ((X) >> (32-(n))))
158 #define MAKE_WORD(b) \
159    ((((_pSLuint32_Type)(b[0]))<<24) | (((_pSLuint32_Type)(b[1]))<<16) \
160      | (((_pSLuint32_Type)(b[2]))<<8) | ((_pSLuint32_Type)(b[3])))
161 
sha1_process_block(SLChksum_Type * sha1,unsigned char * buf)162 static int sha1_process_block (SLChksum_Type *sha1, unsigned char *buf)
163 {
164    _pSLuint32_Type a, b, c, d, e;
165    _pSLuint32_Type w[80];
166    unsigned int t;
167 
168    for (t = 0; t < 16; t++)
169      {
170 	w[t] = MAKE_WORD(buf);
171 	buf += 4;
172      }
173    for (t = 16; t < 80; t++)
174      {
175 	_pSLuint32_Type x = w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16];
176 	w[t] = CSHIFT(1, x);
177      }
178 
179    a = sha1->h[0]; b = sha1->h[1]; c = sha1->h[2]; d = sha1->h[3]; e = sha1->h[4];
180 
181    for (t = 0; t < 20; t++)
182      {
183 	_pSLuint32_Type tmp;
184 	tmp = CSHIFT(5,a) + F_00_19(b,c,d) + e + w[t] + K_00_19;
185 	e = d; d = c; c = CSHIFT(30,b); b = a; a = tmp;
186      }
187    for (t = 20; t < 40; t++)
188      {
189 	_pSLuint32_Type tmp;
190 	tmp = CSHIFT(5,a) + F_20_39(b,c,d) + e + w[t] + K_20_39;
191 	e = d; d = c; c = CSHIFT(30,b); b = a; a = tmp;
192      }
193    for (t = 40; t < 60; t++)
194      {
195 	_pSLuint32_Type tmp;
196 	tmp = CSHIFT(5,a) + F_40_59(b,c,d) + e + w[t] + K_40_59;
197 	e = d; d = c; c = CSHIFT(30,b); b = a; a = tmp;
198      }
199    for (t = 60; t < 80; t++)
200      {
201 	_pSLuint32_Type tmp;
202 	tmp = CSHIFT(5,a) + F_60_79(b,c,d) + e + w[t] + K_60_79;
203 	e = d; d = c; c = CSHIFT(30,b); b = a; a = tmp;
204      }
205 
206    sha1->h[0] += a; sha1->h[1] += b; sha1->h[2] += c; sha1->h[3] += d; sha1->h[4] += e;
207 
208    return 0;
209 }
210 
sha1_accumulate(SLChksum_Type * sha1,unsigned char * buf,unsigned int buflen)211 static int sha1_accumulate (SLChksum_Type *sha1, unsigned char *buf, unsigned int buflen)
212 {
213    unsigned int num_buffered;
214    unsigned char *bufmax;
215 
216    if ((sha1 == NULL) || (buf == NULL))
217      return -1;
218 
219    update_num_bits (sha1, buflen);
220 
221    num_buffered = sha1->num_buffered;
222 
223    if (num_buffered)
224      {
225 	unsigned int dlen = SHA1_BUFSIZE - sha1->num_buffered;
226 
227 	if (buflen < dlen)
228 	  dlen = buflen;
229 
230 	memcpy (sha1->buf+num_buffered, buf, dlen);
231 	num_buffered += dlen;
232 	buflen -= dlen;
233 	buf += dlen;
234 
235 	if (num_buffered < SHA1_BUFSIZE)
236 	  {
237 	     sha1->num_buffered = num_buffered;
238 	     return 0;
239 	  }
240 
241 	sha1_process_block (sha1, sha1->buf);
242 	num_buffered = 0;
243      }
244 
245    num_buffered = buflen % SHA1_BUFSIZE;
246    bufmax = buf + (buflen - num_buffered);
247    while (buf < bufmax)
248      {
249 	sha1_process_block (sha1, buf);
250 	buf += SHA1_BUFSIZE;
251      }
252 
253    if (num_buffered)
254      memcpy (sha1->buf, bufmax, num_buffered);
255 
256    sha1->num_buffered = num_buffered;
257 
258    return 0;
259 }
260 
uint32_to_uchar(_pSLuint32_Type * u,unsigned int num,unsigned char * buf)261 static void uint32_to_uchar (_pSLuint32_Type *u, unsigned int num, unsigned char *buf)
262 {
263    unsigned int i;
264 
265    for (i = 0; i < num; i++)
266      {
267 	_pSLuint32_Type x = u[i];
268 	buf[3] = (unsigned char) (x & 0xFF);
269 	buf[2] = (unsigned char) ((x>>8) & 0xFF);
270 	buf[1] = (unsigned char) ((x>>16) & 0xFF);
271 	buf[0] = (unsigned char) ((x>>24) & 0xFF);
272 	buf += 4;
273      }
274 }
275 
sha1_close(SLChksum_Type * sha1,unsigned char * digest)276 static int sha1_close (SLChksum_Type *sha1, unsigned char *digest)
277 {
278    unsigned char num_bits_buf[8];
279 
280    if (sha1 == NULL)
281      return -1;
282 
283    if (digest != NULL)
284      {
285 	/* Handle num bits before padding */
286 	uint32_to_uchar (sha1->num_bits, 2, num_bits_buf);
287 
288 	/* Add pad and num_bits bytes */
289 	(void) sha1_accumulate (sha1, Pad_Bytes, compute_pad_length (sha1->num_buffered));
290 	(void) sha1_accumulate (sha1, num_bits_buf, 8);
291 	uint32_to_uchar (sha1->h, 5, digest);
292      }
293 
294    SLfree ((char *)sha1);
295    return 0;
296 }
297 
_pSLchksum_sha1_new(char * name)298 SLChksum_Type *_pSLchksum_sha1_new (char *name)
299 {
300    SLChksum_Type *sha1;
301 
302    (void) name;
303    sha1 = (SLChksum_Type *)SLmalloc (sizeof (SLChksum_Type));
304    if (sha1 == NULL)
305      return NULL;
306    memset ((char *)sha1, 0, sizeof (SLChksum_Type));
307 
308    sha1->accumulate = sha1_accumulate;
309    sha1->close = sha1_close;
310    sha1->digest_len = SHA1_DIGEST_LEN;
311 
312    sha1->h[0] = 0x67452301;
313    sha1->h[1] = 0xEFCDAB89;
314    sha1->h[2] = 0x98BADCFE;
315    sha1->h[3] = 0x10325476;
316    sha1->h[4] = 0xC3D2E1F0;
317 
318    return sha1;
319 }
320 
321 #if 0
322 int main (int argc, char **argv)
323 {
324    SLChksum_Type *sha1;
325    unsigned int i;
326    unsigned char buf[1024];
327    unsigned int len;
328    unsigned char digest[SHA1_DIGEST_LEN];
329    char *s;
330 
331    if (NULL == (sha1 = sha1_open ()))
332      return 1;
333 #if 0
334    while (0 != (len = fread (buf, 1, sizeof (buf), stdin)))
335      (void) sha1_accumulate (sha1, buf, len);
336 #else
337    for (i = 0; i < 1000000; i++)
338      {
339 	s = "a";
340 	(void) sha1_accumulate (sha1, s, strlen(s));
341      }
342 #endif
343    sha1_close (sha1, digest);
344 
345    for (i = 0; i < 20; i++)
346      fprintf (stdout, "%02x", digest[i]);
347 
348    fputs ("\n", stdout);
349    return 0;
350 }
351 #endif
352