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