Line data Source code
1 : % Copyright (C) 2012-2021,2022 John E. Davis
2 : %
3 : % This file is part of the S-Lang Library and may be distributed under the
4 : % terms of the GNU General Public License. See the file COPYING for
5 : % more information.
6 : %---------------------------------------------------------------------------
7 2 : import ("chksum");
8 :
9 2 : private variable CRC8_Map = Assoc_Type[Struct_Type];
10 : define chksum_add_crc8_subtype (subtype)
11 : {
12 20 : subtype = strtrans(subtype, "-_", "");
13 20 : CRC8_Map[strlow(subtype)] = @__qualifiers;
14 : }
15 :
16 2 : chksum_add_crc8_subtype(""; poly=0xD5, seed=0x00, refin=0, refout=0, xorout=0x00);
17 2 : chksum_add_crc8_subtype("dvb-s2"; poly=0xD5, seed=0x00, refin=0, refout=0, xorout=0x00);
18 2 : chksum_add_crc8_subtype("cdma2000"; poly=0x9B, seed=0xFF, refin=0, refout=0, xorout=0x00);
19 2 : chksum_add_crc8_subtype("darc"; poly=0x39, seed=0x00, refin=1, refout=1, xorout=0x00);
20 2 : chksum_add_crc8_subtype("ebu"; poly=0x1D, seed=0xFF, refin=1, refout=1, xorout=0x00);
21 2 : chksum_add_crc8_subtype("i-code"; poly=0x1D, seed=0xFD, refin=0, refout=0, xorout=0x00);
22 2 : chksum_add_crc8_subtype("itu"; poly=0x07, seed=0x00, refin=0, refout=0, xorout=0x55);
23 2 : chksum_add_crc8_subtype("maxim"; poly=0x31, seed=0x00, refin=1, refout=1, xorout=0x00);
24 2 : chksum_add_crc8_subtype("rohc"; poly=0x07, seed=0xFF, refin=1, refout=1, xorout=0x00);
25 2 : chksum_add_crc8_subtype("wcdma"; poly=0x9B, seed=0x00, refin=1, refout=1, xorout=0x00);
26 :
27 2 : private variable CRC16_Map = Assoc_Type[Struct_Type];
28 : define chksum_add_crc16_subtype (subtype)
29 : {
30 48 : subtype = strtrans(subtype, "-_", "");
31 48 : CRC16_Map[strlow(subtype)] = @__qualifiers;
32 : }
33 :
34 2 : chksum_add_crc16_subtype(""; poly=0x1021U, seed=0xFFFFU, refin=0, refout=0, xorout=0x0000U);
35 2 : chksum_add_crc16_subtype("ccitt-0"; poly=0x1021U, seed=0xFFFFU, refin=0, refout=0, xorout=0x0000U);
36 2 : chksum_add_crc16_subtype("ARC"; poly=0x8005U, seed=0x0000U, refin=1, refout=1, xorout=0x0000U);
37 2 : chksum_add_crc16_subtype("AUG-CCITT"; poly=0x1021U, seed=0x1D0FU, refin=0, refout=0, xorout=0x0000U);
38 2 : chksum_add_crc16_subtype("BUYPASS"; poly=0x8005U, seed=0x0000U, refin=0, refout=0, xorout=0x0000U);
39 2 : chksum_add_crc16_subtype("CDMA2000"; poly=0xC867U, seed=0xFFFFU, refin=0, refout=0, xorout=0x0000U);
40 2 : chksum_add_crc16_subtype("DDS-110"; poly=0x8005U, seed=0x800DU, refin=0, refout=0, xorout=0x0000U);
41 2 : chksum_add_crc16_subtype("DECT-R"; poly=0x0589U, seed=0x0000U, refin=0, refout=0, xorout=0x0001U);
42 2 : chksum_add_crc16_subtype("DECT-X"; poly=0x0589U, seed=0x0000U, refin=0, refout=0, xorout=0x0000U);
43 2 : chksum_add_crc16_subtype("DNP"; poly=0x3D65U, seed=0x0000U, refin=1, refout=1, xorout=0xFFFFU);
44 2 : chksum_add_crc16_subtype("EN-13757"; poly=0x3D65U, seed=0x0000U, refin=0, refout=0, xorout=0xFFFFU);
45 2 : chksum_add_crc16_subtype("GENIBUS"; poly=0x1021U, seed=0xFFFFU, refin=0, refout=0, xorout=0xFFFFU);
46 2 : chksum_add_crc16_subtype("MAXIM"; poly=0x8005U, seed=0x0000U, refin=1, refout=1, xorout=0xFFFFU);
47 2 : chksum_add_crc16_subtype("MCRF4XX"; poly=0x1021U, seed=0xFFFFU, refin=1, refout=1, xorout=0x0000U);
48 2 : chksum_add_crc16_subtype("RIELLO"; poly=0x1021U, seed=0xB2AAU, refin=1, refout=1, xorout=0x0000U);
49 2 : chksum_add_crc16_subtype("T10-DIF"; poly=0x8BB7U, seed=0x0000U, refin=0, refout=0, xorout=0x0000U);
50 2 : chksum_add_crc16_subtype("TELEDISK"; poly=0xA097U, seed=0x0000U, refin=0, refout=0, xorout=0x0000U);
51 2 : chksum_add_crc16_subtype("TMS37157"; poly=0x1021U, seed=0x89ECU, refin=1, refout=1, xorout=0x0000U);
52 2 : chksum_add_crc16_subtype("USB"; poly=0x8005U, seed=0xFFFFU, refin=1, refout=1, xorout=0xFFFFU);
53 2 : chksum_add_crc16_subtype("A"; poly=0x1021U, seed=0xC6C6U, refin=1, refout=1, xorout=0x0000U);
54 2 : chksum_add_crc16_subtype("KERMIT"; poly=0x1021U, seed=0x0000U, refin=1, refout=1, xorout=0x0000U);
55 2 : chksum_add_crc16_subtype("MODBUS"; poly=0x8005U, seed=0xFFFFU, refin=1, refout=1, xorout=0x0000U);
56 2 : chksum_add_crc16_subtype("X-25"; poly=0x1021U, seed=0xFFFFU, refin=1, refout=1, xorout=0xFFFFU);
57 2 : chksum_add_crc16_subtype("XMODEM"; poly=0x1021U, seed=0x0000U, refin=0, refout=0, xorout=0x0000U);
58 :
59 2 : private variable CRC32_Map = Assoc_Type[Struct_Type];
60 : define chksum_add_crc32_subtype (subtype)
61 : {
62 18 : subtype = strtrans(subtype, "-_", "");
63 18 : CRC32_Map[strlow(subtype)] = @__qualifiers;
64 : }
65 :
66 2 : chksum_add_crc32_subtype(""; poly=0x04C11DB7U, seed=0xFFFFFFFFU, refin=1, refout=1, xorout=0xFFFFFFFFU);
67 2 : chksum_add_crc32_subtype("BZIP2"; poly=0x04C11DB7U, seed=0xFFFFFFFFU, refin=0, refout=0, xorout=0xFFFFFFFFU);
68 2 : chksum_add_crc32_subtype("C"; poly=0x1EDC6F41U, seed=0xFFFFFFFFU, refin=1, refout=1, xorout=0xFFFFFFFFU);
69 2 : chksum_add_crc32_subtype("D"; poly=0xA833982BU, seed=0xFFFFFFFFU, refin=1, refout=1, xorout=0xFFFFFFFFU);
70 2 : chksum_add_crc32_subtype("MPEG-2"; poly=0x04C11DB7U, seed=0xFFFFFFFFU, refin=0, refout=0, xorout=0x00000000U);
71 2 : chksum_add_crc32_subtype("POSIX"; poly=0x04C11DB7U, seed=0x00000000U, refin=0, refout=0, xorout=0xFFFFFFFFU);
72 2 : chksum_add_crc32_subtype("Q"; poly=0x814141ABU, seed=0x00000000U, refin=0, refout=0, xorout=0x00000000U);
73 2 : chksum_add_crc32_subtype("JAMCRC"; poly=0x04C11DB7U, seed=0xFFFFFFFFU, refin=1, refout=1, xorout=0x00000000U);
74 2 : chksum_add_crc32_subtype("XFER"; poly=0x000000AFU, seed=0x00000000U, refin=0, refout=0, xorout=0x00000000U);
75 :
76 : private define parse_name (name)
77 : {
78 94208 : name = strlow (name);
79 94208 : variable q = __qualifiers;
80 94208 : variable subtype = qualifier ("type", NULL);
81 94208 : variable words = strchop (name, '/', 0);
82 :
83 : % Convert crc-8 to crc8, i-code to icode, etc
84 94208 : name = strtrans(words[0], "-_", "");
85 94208 : if (strncmp(name, "crc", 3))
86 93990 : return name, q;
87 :
88 218 : if (length (words) > 1)
89 40 : subtype = words[1];
90 178 : else if (subtype == NULL)
91 : {
92 178 : if (q != NULL)
93 172 : return name, q;
94 6 : subtype = "";
95 : }
96 :
97 46 : subtype = strtrans (strlow (subtype), "-_", "");
98 46 : variable map = NULL;
99 :
100 46 : if (name == "crc8")
101 11 : map = CRC8_Map;
102 35 : else if (name == "crc16")
103 25 : map = CRC16_Map;
104 10 : else if (name == "crc32")
105 10 : map = CRC32_Map;
106 :
107 46 : if ((map != NULL)
108 : && assoc_key_exists (map, subtype))
109 46 : return name, map[subtype];
110 :
111 0 : throw UndefinedNameError, "Unknown $name type: $subtype"$;
112 : }
113 :
114 : private define chksum_accumulate (c, str)
115 : {
116 282353 : _chksum_accumulate (c.obj, str);
117 : }
118 :
119 : private define chksum_close (c)
120 : {
121 94089 : variable chksum = _chksum_close (c.obj;; __qualifiers);
122 94089 : c.obj = NULL;
123 94089 : return chksum;
124 : }
125 :
126 : private define chksum_digest_length (c)
127 : {
128 0 : return _chksum_digest_length(c.obj);
129 : }
130 :
131 : private define chksum_buffer_size (c)
132 : {
133 0 : return _chksum_buffer_size(c.obj);
134 : }
135 :
136 : define chksum_new (name)
137 : {
138 : variable q;
139 94098 : (name, q) = parse_name (name;; __qualifiers);
140 94098 : return struct
141 : {
142 94098 : obj = _chksum_new (name;; q),
143 94098 : accumulate = &chksum_accumulate,
144 94098 : close = &chksum_close,
145 94098 : digest_length = &chksum_digest_length,
146 94098 : buffer_size = &chksum_buffer_size,
147 94098 : name = name,
148 : };
149 : }
150 :
151 :
152 : define chksum_file (fp, type)
153 : {
154 : variable q;
155 67 : (type, q) = parse_name (type;; __qualifiers);
156 :
157 67 : variable file = NULL;
158 67 : if (typeof (fp) != File_Type)
159 : {
160 67 : file = fp;
161 67 : fp = fopen (file, "rb");
162 67 : if (fp == NULL)
163 0 : throw OpenError, "Error opening $file"$;
164 : }
165 :
166 67 : variable c = _chksum_new (type;; q);
167 :
168 : variable buf;
169 128 : while (-1 != fread_bytes (&buf, 4096, fp))
170 : {
171 61 : _chksum_accumulate (c, buf);
172 : }
173 : % Allow the interpreter to close fp when it goes out of scope
174 67 : return _chksum_close (c);
175 : }
176 :
177 : define md5sum_new ()
178 : {
179 1 : return chksum_new ("md5");
180 : }
181 :
182 : define md5sum (str)
183 : {
184 4 : variable c = _chksum_new ("md5");
185 4 : _chksum_accumulate (c, str);
186 4 : return _chksum_close (c;; __qualifiers);
187 : }
188 :
189 : define md5sum_file (file)
190 : {
191 4 : return chksum_file (file, "md5");
192 : }
193 :
194 : define sha1sum_new ()
195 : {
196 1 : return chksum_new ("sha1");
197 : }
198 :
199 : define sha1sum (str)
200 : {
201 4 : variable c = _chksum_new ("sha1");
202 4 : _chksum_accumulate (c, str);
203 4 : return _chksum_close (c;; __qualifiers);
204 : }
205 :
206 : define sha1sum_file (file)
207 : {
208 4 : return chksum_file (file, "sha1");
209 : }
210 :
211 : define crc8_new ()
212 : {
213 1 : return chksum_new ("crc8";; __qualifiers);
214 : }
215 :
216 : define crc8sum (str)
217 : {
218 : variable name, q;
219 10 : (name, q) = parse_name ("crc8";; __qualifiers);
220 10 : variable c = _chksum_new (name;; q);
221 10 : _chksum_accumulate (c, str);
222 10 : return _chksum_close(c);
223 : }
224 :
225 : define crc8sum_file (file)
226 : {
227 10 : return chksum_file (file, "crc8";; __qualifiers);
228 : }
229 :
230 : define crc16_new ()
231 : {
232 1 : return chksum_new ("crc16";; __qualifiers);
233 : }
234 :
235 : define crc16sum (str)
236 : {
237 : variable name, q;
238 24 : (name, q) = parse_name ("crc16";; __qualifiers);
239 24 : variable c = _chksum_new (name;; q);
240 24 : _chksum_accumulate (c, str);
241 24 : return _chksum_close(c);
242 : }
243 :
244 : define crc16sum_file (file)
245 : {
246 24 : return chksum_file (file, "crc16";; __qualifiers);
247 : }
248 :
249 : define crc32_new ()
250 : {
251 1 : return chksum_new ("crc32";; __qualifiers);
252 : }
253 :
254 : define crc32sum (str)
255 : {
256 : variable name, q;
257 9 : (name, q) = parse_name ("crc32";; __qualifiers);
258 9 : variable c = _chksum_new (name;; q);
259 9 : _chksum_accumulate (c, str);
260 9 : return _chksum_close(c);
261 : }
262 :
263 : define crc32sum_file (file)
264 : {
265 9 : return chksum_file (file, "crc32";; __qualifiers);
266 : }
267 :
268 :
269 : %%%
270 : define sha256sum_new ()
271 : {
272 1 : return chksum_new ("sha256");
273 : }
274 :
275 : define sha256sum (str)
276 : {
277 4 : variable c = _chksum_new ("sha256");
278 4 : _chksum_accumulate (c, str);
279 4 : return _chksum_close (c;; __qualifiers);
280 : }
281 :
282 : define sha256sum_file (file)
283 : {
284 4 : return chksum_file (file, "sha256";; __qualifiers);
285 : }
286 : %%%
287 :
288 : %%%
289 : define sha224sum_new ()
290 : {
291 1 : return chksum_new ("sha224";; __qualifiers);
292 : }
293 :
294 : define sha224sum (str)
295 : {
296 4 : variable c = _chksum_new ("sha224");
297 4 : _chksum_accumulate (c, str);
298 4 : return _chksum_close (c;; __qualifiers);
299 : }
300 :
301 : define sha224sum_file (file)
302 : {
303 4 : return chksum_file (file, "sha224";; __qualifiers);
304 : }
305 : %%%
306 :
307 : %%%
308 : define sha512sum_new ()
309 : {
310 1 : return chksum_new ("sha512");
311 : }
312 :
313 : define sha512sum (str)
314 : {
315 4 : variable c = _chksum_new ("sha512");
316 4 : _chksum_accumulate (c, str);
317 4 : return _chksum_close (c;; __qualifiers);
318 : }
319 :
320 : define sha512sum_file (file)
321 : {
322 4 : return chksum_file (file, "sha512";; __qualifiers);
323 : }
324 : %%%
325 :
326 : %%%
327 : define sha384sum_new ()
328 : {
329 1 : return chksum_new ("sha384");
330 : }
331 :
332 : define sha384sum (str)
333 : {
334 4 : variable c = _chksum_new ("sha384");
335 4 : _chksum_accumulate (c, str);
336 4 : return _chksum_close (c;; __qualifiers);
337 : }
338 :
339 : define sha384sum_file (file)
340 : {
341 4 : return chksum_file (file, "sha384";; __qualifiers);
342 : }
343 : %%%
344 :
345 : private define hmac_close (h)
346 : {
347 0 : variable inner = _chksum_close(h.obj; binary);
348 0 : h.obj = NULL;
349 :
350 0 : _chksum_accumulate(h.obj2, inner);
351 :
352 0 : variable r = _chksum_close(h.obj2;; __qualifiers);
353 0 : h.obj2 = NULL;
354 :
355 0 : return r;
356 : }
357 :
358 : define hmac_new (name, key)
359 : {
360 0 : variable obj = _chksum_new(name);
361 0 : variable obj2 = _chksum_new(name);
362 0 : variable tmp = _chksum_new(name);
363 0 : _chksum_accumulate(tmp, key);
364 0 : variable kk = _chksum_close(tmp; binary);
365 :
366 0 : if ((typeof(kk) != BString_Type) && (typeof(kk) != String_Type))
367 : {
368 0 : throw UsageError, "HMAC requires a hash function producing a binary string";
369 : }
370 0 : variable dlen = _chksum_buffer_size(obj);
371 0 : if (dlen <= 0)
372 : {
373 0 : throw UsageError, "HMAC requires a secure hash function";
374 : }
375 :
376 0 : if (bstrlen(key)>dlen)
377 : {
378 0 : key = kk;
379 : }
380 :
381 : % generate inner padding array
382 0 : variable kip = bstring_to_array(key+("\0"B)[[0:dlen-bstrlen(key)-1]/dlen]);
383 0 : kip = array_to_bstring(typecast(kip xor '\x36', UChar_Type));
384 0 : _chksum_accumulate(obj, kip);
385 :
386 : % generate outer padding array
387 0 : variable kop = bstring_to_array(key+("\0"B)[[0:dlen-bstrlen(key)-1]/dlen]);
388 0 : kop = array_to_bstring(typecast(kop xor '\x5c', UChar_Type));
389 0 : _chksum_accumulate(obj2, kop);
390 :
391 0 : return struct
392 : {
393 0 : obj = obj,
394 0 : obj2 = obj2,
395 0 : name = name,
396 0 : close = &hmac_close,
397 0 : accumulate = &chksum_accumulate,
398 : };
399 : }
|