2 * tfcrypt -- high security Threefish encryption tool.
4 * tfcrypt is copyrighted:
5 * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
7 * tfcrypt is licensed to you under the terms of std. MIT/X11 license:
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sublicense, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 void skein(void *hash, size_t bits, const void *key, const void *data, size_t szdata)
36 if (key) skein_init_key(&sk, key, bits);
37 else skein_init(&sk, bits);
38 skein_update(&sk, data, szdata);
39 skein_final(hash, &sk);
42 void tf_key_tweak_compat(void *key)
44 TF_UNIT_TYPE *ukey = key, c = THREEFISH_CONST;
47 for (x = 0; x < TF_NR_BLOCK_UNITS; x++) c ^= ukey[x];
49 ukey[TF_TWEAK_WORD3] = ukey[TF_TWEAK_WORD1] ^ ukey[TF_TWEAK_WORD2];
52 tfc_yesno skeinfd(void *hash, size_t bits, const void *key, int fd, tfc_fsize offset, tfc_fsize readto)
54 static tfc_byte skblk[TFC_BLKSIZE];
58 size_t ldone, lblock, lrem, lio;
62 if (ctr_mode == TFC_MODE_SKSUM) total_processed_src = total_processed_dst = delta_processed = 0;
64 if (fd == -1) goto _fail;
66 if (readto == NOFSIZE) {
67 readto = tfc_fdsize(fd);
68 if (readto == NOFSIZE) goto _fail;
70 if (offset != 0 && offset != NOFSIZE) {
71 if (lseek(fd, (off_t)offset, SEEK_SET) == -1) {
72 if (ignore_seek_errors == NO) goto _fail;
77 if (key) skein_init_key(&sk, key, bits);
78 else skein_init(&sk, bits);
85 lblock = lrem = blk_len_adj(readto, total, TFC_BLKSIZE);
87 if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(fd);
88 _again: lio = xread(fd, pblk, lrem);
89 if (lio == 0) stop = YES;
90 if (lio != NOSIZE) ldone += lio;
92 if (errno != EIO && catch_all_errors != YES) goto _fail;
93 switch (error_action) {
94 case TFC_ERRACT_CONT: xerror(YES, NO, NO, "skeinfd: %d", fd); goto _again; break;
96 case TFC_ERRACT_LSYNC:
97 xerror(YES, NO, NO, "skeinfd: %d", fd);
98 lio = lrem = ldone = lblock;
100 memset(skblk, 0, lio);
101 if (rdpos == NOFSIZE) lseek(fd, lio, SEEK_CUR);
102 else lseek(fd, rdpos + lio, SEEK_SET);
104 default: goto _fail; break;
107 if (lio && lio < lrem) {
113 if (ctr_mode == TFC_MODE_SKSUM) {
114 total_processed_src = total_processed_dst = total;
115 delta_processed += ldone;
117 skein_update(&sk, skblk, ldone);
118 if (readto != NOFSIZE && total >= readto) break;
121 if (fd > 2) lseek(fd, (off_t)readto, SEEK_SET);
123 skein_final(hash, &sk);
124 if (ctr_mode == TFC_MODE_SKSUM) {
125 if (verbose || status_timer) print_crypt_status(-1);
126 total_processed_src = total_processed_dst = delta_processed = 0;
128 memset(skblk, 0, TFC_BLKSIZE);
132 memset(&sk, 0, sizeof(struct skein));
133 memset(hash, 0, SKEIN_DIGEST_SIZE);
134 memset(skblk, 0, TFC_BLKSIZE);
138 void do_sksum(char *spec, char **fargv)
140 static char sksblk[TFC_BLKSIZE / 2], tmp[TFC_TMPSIZE];
141 tfc_byte hash[SKEIN_DIGEST_SIZE];
146 if (macbits < TF_MAX_BITS) {
151 if (!strcmp(spec, "sksum")) {
156 if ((sscanf(spec, "sk%zusum", &bits) < 1)) {
160 if (bits < 8 || bits > TF_MAX_BITS) {
162 "%u: invalid bits number specified!\n"
163 "tfcrypt supports from 8 to %u bits, divisible by 8.",
164 bits, TFC_U(TF_MAX_BITS));
167 if (!bits || bits % 8) {
169 "%u: invalid bits number specified!\n"
170 "Number of bits must start from 8 and be divisible by 8.",
171 bits, TFC_U(TF_MAX_BITS));
175 do_edcrypt = TFC_DO_PLAIN;
176 ctr_mode = TFC_MODE_SKSUM;
178 for (x = 1; x < NSIG; x++) signal(x, SIG_IGN);
179 memset(&sigact, 0, sizeof(sigact));
180 sigact.sa_flags = SA_RESTART;
181 sigact.sa_handler = print_crypt_status;
182 sigaction(SIGUSR1, &sigact, NULL);
183 sigaction(SIGTSTP, &sigact, NULL);
184 sigaction(SIGALRM, &sigact, NULL);
185 sigact.sa_handler = change_status_width;
186 sigaction(SIGQUIT, &sigact, NULL);
187 sigact.sa_handler = change_status_timer;
188 sigaction(SIGUSR2, &sigact, NULL);
189 sigact.sa_handler = exit_sigterm;
190 sigaction(SIGINT, &sigact, NULL);
191 sigaction(SIGTERM, &sigact, NULL);
192 memset(&sigact, 0, sizeof(struct sigaction));
194 tfc_getcurtime(&delta_time);
196 if (sksum_hashlist_file) {
198 char *s, *d, *t, *shash, *fname;
199 int failed = 0, totaltested = 0;
201 if (!strcmp(sksum_hashlist_file, "-")) f = stdin;
202 else f = fopen(sksum_hashlist_file, "r");
203 if (!f) xerror(NO, NO, YES, "%s", sksum_hashlist_file);
206 memset(sksblk, 0, sizeof(sksblk));
207 if (xfgets(sksblk, sizeof(sksblk), f) != YES) break;
209 s = d = sksblk; t = NULL;
210 shash = fname = NULL;
211 while ((s = strtok_r(d, "\t", &t))) {
214 if (!shash) shash = s;
215 else if (shash && !fname) fname = s;
218 if (!shash || !fname) {
219 xerror(YES, NO, YES, "invalid string %s", sksblk);
224 s = strchr(shash, ' ');
225 if (s && s[1] == ' ') *s = 0;
227 fd = open(fname, O_RDONLY | O_LARGEFILE);
229 xerror(YES, NO, YES, "%s", fname);
234 if (status_timer) setup_next_alarm(status_timer);
235 if (skeinfd(hash, bits, mackey_opt ? mackey : NULL, fd, iseek, maxlen) != YES) {
236 xerror(YES, NO, YES, "%s", fname);
241 if (sksum_turns > 1) {
243 for (y = 0; y < sksum_turns; y++)
244 skein(hash, bits, mackey_opt ? mackey : NULL, hash, TF_FROM_BITS(bits));
246 if (isbase64(shash)) base64_decode(tmp, sizeof(tmp), shash, strlen(shash));
247 else hex2bin(tmp, shash);
249 if (!memcmp(hash, tmp, TF_FROM_BITS(bits))) {
250 tfc_say("%s: OK", fname);
253 tfc_say("%s: FAILED", fname);
256 memset(tmp, 0, sizeof(tmp));
257 memset(sksblk, 0, sizeof(sksblk));
263 tfc_esay("%s: WARNING: %u of %u computed checksums did NOT match",
264 progname, failed, totaltested);
270 for (xx = 0; fargv[xx]; xx++);
277 for (x = 0; fargv[x] && xx; x++) {
278 if (!strcmp(fargv[x], "-")) fd = 0;
279 else fd = open(fargv[x], O_RDONLY | O_LARGEFILE);
281 xerror(YES, NO, YES, "%s", fargv[x]);
286 _dohash: if (status_timer) setup_next_alarm(status_timer);
287 if (skeinfd(hash, bits, mackey_opt ? mackey : NULL, fd, iseek, maxlen) != YES) {
288 xerror(YES, NO, YES, "%s", fargv[x]);
293 if (sksum_turns > 1) {
295 for (y = 0; y < sksum_turns; y++) skein(hash, bits, mackey_opt ? mackey : NULL, hash, TF_FROM_BITS(bits));
297 if (do_outfmt == TFC_OUTFMT_B64) tfc_printbase64(stdout, hash, TF_FROM_BITS(bits), 0);
298 else if (do_outfmt == TFC_OUTFMT_RAW) xwrite(1, hash, TF_FROM_BITS(bits));
299 else mhexdump(hash, TF_FROM_BITS(bits), TF_FROM_BITS(bits), 0);
300 if (do_outfmt != TFC_OUTFMT_RAW) {
301 if (quiet == NO || xx > 1) tfc_say("\t%s", fargv[x] ? fargv[x] : "-");
306 memset(hash, 0, SKEIN_DIGEST_SIZE);