* tfcrypt -- high security Threefish encryption tool.
*
* tfcrypt is copyrighted:
- * Copyright (C) 2012-2018 Andrey Rys. All rights reserved.
+ * Copyright (C) 2012-2019 Andrey Rys. All rights reserved.
*
* tfcrypt is licensed to you under the terms of std. MIT/X11 license:
*
#include "tfcrypt.h"
+static tfc_byte svctr[TF_BLOCK_SIZE];
+
+static void open_log(const char *logfile)
+{
+ int fd;
+
+ fd = open(logfile, O_WRONLY | O_CREAT | O_LARGEFILE | O_TRUNC, 0666);
+ if (fd == -1) xerror(NO, NO, YES, "%s", logfile);
+ xclose(2);
+ if (dup2(fd, 2) == -1) xexit(2);
+ xclose(fd);
+ do_statline_dynamic = NO;
+}
+
static int getps_filter(struct getpasswd_state *getps, char chr, size_t pos)
{
if (chr == '\x03') {
return 0;
}
+static inline int isctrlchr(int c)
+{
+ if (c == 9) return 0;
+ if (c >= 0 && c <= 31) return 1;
+ if (c == 127) return 1;
+ return 0;
+}
+
+static int getps_plain_filter(struct getpasswd_state *getps, char chr, size_t pos)
+{
+ int x;
+
+ x = getps_filter(getps, chr, pos);
+ if (x != 1) return x;
+
+ if (pos < getps->pwlen && !isctrlchr(chr))
+ write(getps->efd, &chr, sizeof(char));
+ return 1;
+}
+
+static int getps_plain_hex_filter(struct getpasswd_state *getps, char chr, size_t pos)
+{
+ int x;
+
+ x = getps_hex_filter(getps, chr, pos);
+ if (x != 1) return x;
+
+ if (pos < getps->pwlen && !isctrlchr(chr))
+ write(getps->efd, &chr, sizeof(char));
+ return 1;
+}
+
+static void make_hint(void *hint, size_t szhint, const void *data, size_t szdata)
+{
+ char t[TF_FROM_BITS(TF_MAX_BITS)];
+
+ skein(t, TF_MAX_BITS, NULL, data, szdata);
+ xor_shrink(hint, szhint, t, sizeof(t));
+ memset(t, 0, sizeof(t));
+}
+
+static void raw_say_hint(void *hint, size_t szhint, const void *data, size_t szdata, const char *prompt)
+{
+ make_hint(hint, szhint, data, szdata);
+ if (prompt) tfc_nfsay(stderr, "%s: ", prompt);
+ mehexdump(hint, szhint, szhint, 1);
+ memset(hint, 0, szhint);
+}
+
+static void say_hint(const void *data, size_t szdata, const char *prompt)
+{
+ char t[TF_SIZE_UNIT];
+ raw_say_hint(t, TF_SIZE_UNIT, data, szdata, prompt);
+ /* t[] is erased (automatically) */
+}
+
int main(int argc, char **argv)
{
int c;
double td;
char *s, *d, *t, *stoi;
size_t x, n;
+ tfc_fsize rwd;
progname = basename(argv[0]);
if (!isatty(2)) do_statline_dynamic = NO;
+ s = (char *)srcblk;
+ d = getenv("HOME");
+ if (!d) d = "";
+ n = PATH_MAX > sizeof(srcblk) ? sizeof(srcblk) : PATH_MAX;
+ if (xstrlcpy(s, d, n) >= n) goto _baddfname;
+ if (xstrlcat(s, "/.tfcrypt.defs", n) >= n) goto _baddfname;
+ read_defaults(s, YES);
+_baddfname:
+ memset(s, 0, n);
+
+ if (!strcmp(progname, "iotool")) {
+ do_edcrypt = TFC_DO_PLAIN;
+ password = YES;
+ ctr_mode = TFC_MODE_PLAIN;
+ }
+
opterr = 0;
- while ((c = getopt(argc, argv, "aU:C:r:K:t:TPkzxc:l:qedn:vV:pwE:O:S:AmM:R:Z:WHD:")) != -1) {
+ while ((c = getopt(argc, argv, "L:s:aU:C:r:K:t:Pkzxc:l:qedn:vV:pwE:o:O:S:AmuM:R:Z:WHD:")) != -1) {
switch (c) {
+ case 'L':
+ read_defaults(optarg, NO);
+ break;
+ case 's':
+ saltf = optarg;
+ break;
case 'r':
randsource = optarg;
break;
counter_opt = TFC_CTR_HEAD;
else if (!strcasecmp(optarg, "rand"))
counter_opt = TFC_CTR_RAND;
+ else if (!strcasecmp(optarg, "zero"))
+ counter_opt = TFC_CTR_ZERO;
+ else if (strchr(optarg, ':')) {
+ char *ss, chr;
+
+ counter_opt = TFC_CTR_SSET;
+ n = sizeof(ctr);
+
+ s = d = optarg; t = NULL;
+ while ((s = strtok_r(d, ",", &t))) {
+ if (d) d = NULL;
+
+ if (n == 0) break;
+ ss = strchr(s, ':');
+ if (!ss) continue;
+ *ss = 0; ss++;
+ chr = (char)strtoul(s, &stoi, 16);
+ if (!str_empty(stoi)) continue;
+ x = (size_t)strtoul(ss, &stoi, 10);
+ if (!str_empty(stoi)) continue;
+ if (x > n) x = n;
+ memset(ctr+(sizeof(ctr)-n), (int)chr, x);
+ n -= x;
+ }
+ }
else counter_file = sksum_hashlist_file = optarg;
break;
case 'C':
ctr_mode = TFC_MODE_PLAIN;
break;
case 'e':
- do_edcrypt = TFC_DO_ENCRYPT;
+ if (do_edcrypt != TFC_DO_PLAIN) do_edcrypt = TFC_DO_ENCRYPT;
break;
case 'd':
- do_edcrypt = TFC_DO_DECRYPT;
+ if (do_edcrypt != TFC_DO_PLAIN) do_edcrypt = TFC_DO_DECRYPT;
break;
case 'D':
macbits = strtoul(optarg, &stoi, 10);
break;
case 't':
tweakf = optarg;
- break;
- case 'T':
- do_tfcrypt1 = YES;
+ do_full_key = NO;
break;
case 'l':
if (maxlen != NOFSIZE) break;
catch_all_errors = YES;
break;
}
+ if (!strcmp(optarg, "xseek")) {
+ ignore_seek_errors = YES;
+ break;
+ }
if (!strcmp(optarg, "exit"))
error_action = TFC_ERRACT_EXIT;
else if (!strncmp(optarg, "cont", 4))
error_action = TFC_ERRACT_CONT;
else if (!strcmp(optarg, "sync"))
error_action = TFC_ERRACT_SYNC;
+ else if (!strcmp(optarg, "lsync"))
+ error_action = TFC_ERRACT_LSYNC;
else xerror(NO, YES, YES, "invalid error action %s specified", optarg);
break;
+ case 'o':
+ open_log(optarg);
+ break;
case 'O':
s = d = optarg; t = NULL;
while ((s = strtok_r(d, ",", &t))) {
mac_pw_prompt = s+10;
else if (!strcmp(s, "shorthex"))
do_full_hexdump = NO;
+ else if (!strcmp(s, "fullkey"))
+ do_full_key = YES;
+ else if (!strcmp(s, "showsecrets"))
+ show_secrets = YES;
+ else if (!strncmp(s, "logfile", 7) && *(s+7) == '=')
+ open_log(s+8);
else if (!strncmp(s, "iobs", 4) && *(s+4) == '=') {
s += 5;
blksize = (size_t)tfc_humanfsize(s, &stoi);
if (counter_opt == TFC_CTR_HEAD)
maxlen += TF_BLOCK_SIZE;
}
+ else if (!strncmp(s, "ftrunc", 6) && *(s+6) == '=') {
+ s += 7;
+ if (!strcmp(s, "tail")) {
+ do_ftrunc = TFC_FTRUNC_TAIL;
+ ftrunc_dfd = NOFSIZE;
+ }
+ else {
+ do_ftrunc = TFC_DO_FTRUNC;
+ ftrunc_dfd = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ ftrunc_dfd = tfc_fnamesize(s, YES);
+ ftrunc_dfd = tfc_modifysize(ftrunc_dfd, strchr(s, ':'));
+ if (ftrunc_dfd == NOFSIZE) xerror(NO, YES, YES,
+ "%s: invalid ftrunc value", s);
+ }
+ else ftrunc_dfd = tfc_modifysize(ftrunc_dfd, strchr(s, ':'));
+ }
+ }
else if (!strncmp(s, "xkey", 4) && *(s+4) == '=') {
s += 5;
maxkeylen = tfc_humanfsize(s, &stoi);
if (!str_empty(stoi)) {
- maxkeylen = (size_t)tfc_fnamesize(s, YES);
- maxkeylen = (size_t)tfc_modifysize((tfc_fsize)maxkeylen, strchr(s, ':'));
+ maxkeylen = tfc_fnamesize(s, YES);
+ maxkeylen = tfc_modifysize(maxkeylen, strchr(s, ':'));
if (maxkeylen == NOSIZE)
xerror(NO, YES, YES,
"%s: invalid key length value", s);
}
- else maxkeylen = (size_t)tfc_modifysize((tfc_fsize)maxkeylen, strchr(s, ':'));
+ else maxkeylen = tfc_modifysize(maxkeylen, strchr(s, ':'));
+ }
+ else if (!strncmp(s, "okey", 4) && *(s+4) == '=') {
+ s += 5;
+ keyoffset = tfc_humanfsize(s, &stoi);
+ if (!str_empty(stoi)) {
+ keyoffset = tfc_fnamesize(s, YES);
+ keyoffset = tfc_modifysize(keyoffset, strchr(s, ':'));
+ if (keyoffset == NOFSIZE)
+ xerror(NO, YES, YES,
+ "%s: invalid key offset value", s);
+ }
+ else keyoffset = tfc_modifysize(keyoffset, strchr(s, ':'));
}
else if (!strncmp(s, "xctr", 4) && *(s+4) == '=') {
s += 5;
do_mac_file = optarg;
break;
case 'm':
+ case 'u':
if (do_mac != TFC_MAC_VRFY)
xerror(NO, YES, YES, "signature source was not specified");
do_mac = TFC_MAC_JUST_VRFY;
+ if (c == 'u') do_mac = TFC_MAC_JUST_VRFY2;
break;
case 'R':
case 'Z':
case 'q':
quiet = YES;
verbose = NO;
+ do_full_hexdump = NO;
status_timer = 0;
break;
case 'v':
xerror(NO, YES, YES, "Cannot encrypt and read CTR from source!");
if (overwrite_source && counter_opt == TFC_CTR_RAND)
xerror(NO, YES, YES, "Cannot embed a CTR into file when overwriting it!");
- if (tweakf && do_tfcrypt1 == NO)
- xerror(NO, YES, YES, "Use -T with -t tweakfile to enable old tfcrypt mode!");
if (ctr_mode == TFC_MODE_PLAIN
&& (do_edcrypt || do_mac || rawkey
|| mackey_opt || counter_opt || counter_file))
errno = 0;
do_stop = NO;
+ if (saltf) {
+ int saltfd;
+
+ memset(tfc_salt, 0, TFC_MAX_SALT);
+ tfc_saltsz = 0;
+ if (!strcasecmp(saltf, "disable")) goto _nosalt;
+
+ if (!strcmp(saltf, "-")) saltfd = 0;
+ else saltfd = open(saltf, O_RDONLY | O_LARGEFILE);
+ if (saltfd == -1) xerror(NO, NO, YES, "%s", saltf);
+ lio = xread(saltfd, tfc_salt, TFC_MAX_SALT - TF_FROM_BITS(TFC_KEY_BITS));
+ if (lio == NOSIZE) xerror(NO, NO, YES, "%s", saltf);
+ tfc_saltsz = lio;
+ xclose(saltfd);
+ }
+
+_nosalt:
if (mackey_opt == TFC_MACKEY_FILE && mackeyf) {
int mkfd = -1;
tfc_yesno do_stop;
pblk = tmpdata;
ldone = 0;
lrem = lblock = sizeof(tmpdata);
-_mkragain: lio = read(mkfd, pblk, lrem);
- if (lio == 0) do_stop = YES;
+ if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(mkfd);
+_mkragain: lio = xread(mkfd, pblk, lrem);
+ if (lio == 0 && do_stop == NO) do_stop = YES;
if (lio != NOSIZE) ldone += lio;
else {
if (errno != EIO && catch_all_errors != YES)
switch (error_action) {
case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", mackeyf); goto _mkragain; break;
case TFC_ERRACT_SYNC:
+ case TFC_ERRACT_LSYNC:
xerror(YES, NO, NO, "%s", mackeyf);
lio = ldone = lrem = lblock;
memset(tmpdata, 0, lio);
- lseek(mkfd, lio, SEEK_CUR);
+ if (rdpos == NOFSIZE) lseek(mkfd, lio, SEEK_CUR);
+ else lseek(mkfd, rdpos + lio, SEEK_SET);
break;
default: xerror(NO, NO, NO, "%s", mackeyf); break;
}
getps.passwd = pwdask;
getps.pwlen = sizeof(pwdask)-1;
getps.echo = mac_pw_prompt ? mac_pw_prompt : "Enter MAC password: ";
- getps.charfilter = getps_filter;
- getps.maskchar = 'x';
+ getps.charfilter = (show_secrets == YES) ? getps_plain_filter : getps_filter;
+ getps.maskchar = (show_secrets == YES) ? 0 : 'x';
getps.flags = GETP_WAITFILL;
n = xgetpasswd(&getps);
if (n == NOSIZE) xerror(NO, NO, YES, "getting MAC password");
if (n == ((size_t)-2)) xexit(1);
+ if (verbose) say_hint(pwdask, n, "MAC password hint");
skein(mackey, TF_MAX_BITS, NULL, pwdask, n);
- if (verbose) {
- skein(tmpdata, TF_MAX_BITS, NULL, mackey, TF_FROM_BITS(TF_MAX_BITS));
- xor_shrink(tmpdata+TF_FROM_BITS(TF_MAX_BITS), TF_SIZE_UNIT, tmpdata, TF_FROM_BITS(TF_MAX_BITS));
- tfc_nfsay(stderr, "MAC password hint: ");
- mehexdump(tmpdata+TF_FROM_BITS(TF_MAX_BITS), TF_SIZE_UNIT, TF_SIZE_UNIT, 1);
- memset(tmpdata, 0, sizeof(tmpdata));
- }
}
else password = YES;
errno = 0;
- if (do_tfcrypt1 == YES && tweakf) {
+ if (do_full_key == NO && tweakf) {
int twfd;
if (!strcmp(tweakf, "-")) twfd = 0;
else twfd = open(tweakf, O_RDONLY | O_LARGEFILE);
if (twfd == -1) xerror(NO, NO, YES, "%s", tweakf);
- lio = ldone = read(twfd, key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_SIZE_UNIT);
+ lio = ldone = xread(twfd, tweak, TF_TWEAK_SIZE);
if (lio == NOSIZE) xerror(NO, NO, YES, "%s", tweakf);
- if (ldone < 2*TF_SIZE_UNIT)
- xerror(NO, NO, YES, "%s: %zu bytes tweak required", tweakf, 2*TF_SIZE_UNIT);
+ if (ldone < TF_TWEAK_SIZE)
+ xerror(NO, NO, YES, "%s: %zu bytes tweak required", tweakf, TF_TWEAK_SIZE);
xclose(twfd);
}
if (!strcmp(counter_file, "-")) ctrfd = 0;
else ctrfd = open(counter_file, O_RDONLY | O_LARGEFILE);
if (ctrfd == -1) xerror(NO, NO, YES, "%s", counter_file);
- lio = read(ctrfd, ctr, ctrsz);
+ lio = xread(ctrfd, ctr, ctrsz);
if (lio == NOSIZE) xerror(NO, NO, YES, "%s", counter_file);
if (lio < ctrsz) xerror(NO, YES, YES, "counter file is too small (%zu)!", lio);
xclose(ctrfd);
pblk = ctr;
ldone = 0;
lrem = lblock = ctrsz;
-_ctrragain: lio = read(sfd, pblk, lrem);
+ if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
+_ctrragain: lio = xread(sfd, pblk, lrem);
if (lio != NOSIZE) ldone += lio;
else {
if (errno != EIO && catch_all_errors != YES)
switch (error_action) {
case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ctrragain; break;
case TFC_ERRACT_SYNC:
+ case TFC_ERRACT_LSYNC:
xerror(YES, NO, NO, "%s", srcfname);
lio = ldone = lrem = lblock;
memset(ctr, 0, lio);
- lseek(sfd, lio, SEEK_CUR);
+ if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+ else lseek(sfd, rdpos + lio, SEEK_SET);
break;
default: xerror(NO, NO, NO, "%s", srcfname); break;
}
if (counter_opt == TFC_CTR_HEAD && ctr_mode != TFC_MODE_ECB)
iseek += ctrsz;
if (lseek(sfd, iseek, SEEK_SET) == -1)
- xerror(YES, NO, NO, "%s: seek failed", srcfname);
+ xerror(ignore_seek_errors, NO, NO, "%s: seek failed", srcfname);
}
if (ctr_mode == TFC_MODE_PLAIN) goto _plain;
pblk = key;
_xts2key: ldone = 0;
lrem = lblock = TF_FROM_BITS(TFC_KEY_BITS);
-_keyragain: lio = read(kfd, pblk, lrem);
+ if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(kfd);
+_keyragain: lio = xread(kfd, pblk, lrem);
if (lio != NOSIZE) ldone += lio;
else {
if (errno != EIO && catch_all_errors != YES)
switch (error_action) {
case TFC_ERRACT_CONT: xerror(YES, NO, NO, "reading key"); goto _keyragain; break;
case TFC_ERRACT_SYNC:
+ case TFC_ERRACT_LSYNC:
xerror(YES, NO, NO, "reading key");
lio = ldone = lrem = lblock;
memset(key, 0, lio);
- lseek(kfd, lio, SEEK_CUR);
+ if (rdpos == NOFSIZE) lseek(kfd, lio, SEEK_CUR);
+ else lseek(kfd, rdpos + lio, SEEK_SET);
break;
default: xerror(NO, NO, NO, "reading key"); break;
}
getps.passwd = (char *)pblk;
getps.pwlen = n;
getps.echo = pw_prompt ? pw_prompt : "Enter rawkey (str): ";
- getps.charfilter = getps_filter;
- getps.maskchar = 'x';
+ getps.charfilter = (show_secrets == YES) ? getps_plain_filter : getps_filter;
+ getps.maskchar = (show_secrets == YES) ? 0 : 'x';
getps.flags = GETP_WAITFILL;
n = xgetpasswd(&getps);
if (n == NOSIZE) xerror(NO, NO, YES, "getting string rawkey");
if (n == ((size_t)-2)) xexit(1);
+ if (verbose) say_hint(pblk, n, "Raw string key hint");
if (ctr_mode == TFC_MODE_XTS) {
if (xtskeyset == NO) {
pblk = xtskey; n = sizeof(xtskey);
getps.passwd = pwdask;
getps.pwlen = (TF_FROM_BITS(TFC_KEY_BITS)*2);
getps.echo = pw_prompt ? pw_prompt : "Enter rawkey (hex): ";
- getps.charfilter = getps_hex_filter;
- getps.maskchar = 'x';
+ getps.charfilter = (show_secrets == YES) ? getps_plain_hex_filter : getps_hex_filter;
+ getps.maskchar = (show_secrets == YES) ? 0 : 'x';
getps.flags = GETP_WAITFILL;
n = xgetpasswd(&getps);
if (n == NOSIZE) xerror(NO, NO, YES, "getting hex rawkey");
}
hex2bin(pblk, pwdask);
memset(pwdask, 0, sizeof(pwdask));
+ if (verbose) say_hint(pblk, n/2, "Raw hex key hint");
if (ctr_mode == TFC_MODE_XTS) {
if (xtskeyset == NO) {
pblk = xtskey;
getps.passwd = pwdask;
getps.pwlen = sizeof(pwdask)-1;
getps.echo = pw_prompt ? pw_prompt : "Enter password: ";
- getps.charfilter = getps_filter;
- getps.maskchar = 'x';
+ getps.charfilter = (show_secrets == YES) ? getps_plain_filter : getps_filter;
+ getps.maskchar = (show_secrets == YES) ? 0 : 'x';
getps.flags = GETP_WAITFILL;
n = xgetpasswd(&getps);
if (n == NOSIZE) xerror(NO, NO, YES, "getting password");
goto _pwdagain;
}
}
+ if (verbose) say_hint(pwdask, n, "Password hint");
skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, pwdask, n);
memset(pwdask, 0, sizeof(pwdask));
memset(pwdagain, 0, sizeof(pwdagain));
}
else {
- if (skeinfd(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, kfd, maxkeylen) != YES)
+ if (skeinfd(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, kfd, keyoffset, maxkeylen) != YES)
xerror(NO, NO, YES, "hashing key");
}
- if (nr_turns > 1 && rawkey == NO) {
- for (x = 0; x < nr_turns; x++)
+ if (rawkey == NO) {
+ if (tfc_saltsz > 0) {
+ memcpy(tfc_salt+tfc_saltsz, key, TF_FROM_BITS(TFC_KEY_BITS));
+ skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, tfc_salt, tfc_saltsz+TF_FROM_BITS(TFC_KEY_BITS));
+ }
+ if (nr_turns > 1) for (x = 0; x < nr_turns; x++)
skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
+ memset(tfc_salt, 0, TFC_MAX_SALT);
}
if (ctr_mode == TFC_MODE_XTS && rawkey == NO) {
if (!strcmp(genkeyf, "-")) krfd = 1;
else krfd = open(genkeyf, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
if (krfd == -1) xerror(NO, NO, YES, "%s", genkeyf);
-_xts2genkey: if (write(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == -1) xerror(NO, NO, YES, "%s", genkeyf);
+_xts2genkey: if (xwrite(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == NOSIZE) xerror(NO, NO, YES, "%s", genkeyf);
if (do_fsync && fsync(krfd) == -1) xerror(NO, NO, YES, "%s", genkeyf);
if (verbose && xtskeyset == NO) {
tfc_esay("%s: password hashing done", progname);
tf_convkey(key);
if (ctr_mode == TFC_MODE_XTS) tf_convkey(xtskey);
- if (do_tfcrypt1 == YES) {
- if (!tweakf) skein(key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_UNIT_BITS, NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
- tf_key_tweak_compat(key);
+ if (do_full_key == NO) {
+ if (!tweakf) skein(tweak, TF_NR_TWEAK_BITS, NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
+ tf_tweak_set(key, tweak);
}
- if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr);
if (ctr_mode == TFC_MODE_ECB) goto _ctrskip2;
+
+ if (counter_opt == TFC_CTR_ZERO) memset(ctr, 0, ctrsz);
+
tfc_data_to_words64(&iseek_blocks, sizeof(iseek_blocks));
tf_ctr_set(ctr, &iseek_blocks, sizeof(iseek_blocks));
+ if (do_mac == TFC_MAC_JUST_VRFY2) memcpy(svctr, ctr, TF_BLOCK_SIZE);
- switch (counter_opt) {
- case TFC_CTR_SHOW:
- switch (do_outfmt) {
- case TFC_OUTFMT_B64: tfc_printbase64(stderr, ctr, ctrsz, YES); break;
- case TFC_OUTFMT_RAW: write(2, ctr, ctrsz); break;
- case TFC_OUTFMT_HEX: mhexdump(ctr, ctrsz, ctrsz, YES); break;
- }
- break;
- case TFC_CTR_RAND: tfc_getrandom(ctr, ctrsz); break;
+ if (counter_opt == TFC_CTR_SHOW) {
+ switch (do_outfmt) {
+ case TFC_OUTFMT_B64: tfc_printbase64(stderr, ctr, ctrsz, YES); break;
+ case TFC_OUTFMT_RAW: xwrite(2, ctr, ctrsz); break;
+ case TFC_OUTFMT_HEX: mehexdump(ctr, ctrsz, ctrsz, YES); break;
+ }
}
+ else if (counter_opt == TFC_CTR_RAND) tfc_getrandom(ctr, ctrsz);
_ctrskip2:
if (kfd != -1) {
if (oseek) {
if (lseek(dfd, oseek, SEEK_SET) == -1)
- xerror(YES, NO, NO, "%s: seek failed", dstfname);
+ xerror(ignore_seek_errors, NO, NO, "%s: seek failed", dstfname);
}
for (x = 1; x < NSIG; x++) signal(x, SIG_IGN);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = print_crypt_status;
sigaction(SIGUSR1, &sigact, NULL);
- sigaction(SIGTSTP, &sigact, NULL);
sigaction(SIGALRM, &sigact, NULL);
- if (status_timer) setup_next_alarm(status_timer);
+ if (status_timer) setup_next_alarm(status_timer > 1000000 ? 1000000 : status_timer);
sigact.sa_handler = change_status_width;
sigaction(SIGQUIT, &sigact, NULL);
sigact.sa_handler = change_status_timer;
sigact.sa_handler = print_crypt_status;
sigaction(SIGINT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
+ sigaction(SIGTSTP, &sigact, NULL);
}
else {
sigact.sa_handler = exit_sigterm;
sigaction(SIGINT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
+ sigact.sa_handler = handle_sigtstp;
+ sigaction(SIGTSTP, &sigact, NULL);
}
memset(&sigact, 0, sizeof(struct sigaction));
pblk = ctr;
lio = lrem = ctrsz;
ldone = 0;
-_ctrwagain: lio = write(dfd, pblk, lrem);
+_ctrwagain: lio = xwrite(dfd, pblk, lrem);
if (lio != NOSIZE) ldone += lio;
else xerror(NO, NO, NO, "%s", dstfname);
if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
delta_processed += ldone;
}
+ if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr);
+
+ if (do_mac == TFC_MAC_JUST_VRFY2) {
+ rwd = tfc_fdgetpos(sfd);
+ if (rwd == NOFSIZE) {
+ tfc_esay("%s: WARNING: input is not seekable, disabling MAC testing mode", progname);
+ do_mac = TFC_MAC_VRFY;
+ }
+ goto _nodecrypt_again_vrfy2;
+
+_decrypt_again_vrfy2:
+ if (lseek(sfd, (off_t)rwd, SEEK_SET) == ((off_t)-1)) {
+ xerror(ignore_seek_errors, NO, YES, "MAC testing seek failed");
+ }
+ total_processed_src = rwd;
+ memcpy(ctr, svctr, TF_BLOCK_SIZE);
+ memset(svctr, 0, TF_BLOCK_SIZE);
+ }
+
+_nodecrypt_again_vrfy2:
errno = 0;
do_stop = NO;
while (1) {
pblk = srcblk;
ldone = 0;
lrem = lblock = blk_len_adj(maxlen, total_processed_src, blksize);
-_ragain: lio = read(sfd, pblk, lrem);
- if (lio == 0) do_stop = TFC_STOP_BEGAN;
+ if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
+_ragain: lio = xread(sfd, pblk, lrem);
+ if (lio == 0) do_stop = YES;
if (lio != NOSIZE) ldone += lio;
else {
if (errno != EIO && catch_all_errors != YES)
switch (error_action) {
case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ragain; break;
case TFC_ERRACT_SYNC:
+ case TFC_ERRACT_LSYNC:
xerror(YES, NO, NO, "%s", srcfname);
lio = ldone = lrem = lblock;
memset(srcblk, 0, lio);
- lseek(sfd, lio, SEEK_CUR);
+ if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+ else lseek(sfd, rdpos + lio, SEEK_SET);
break;
default: xerror(NO, NO, NO, "%s", srcfname); break;
}
if (do_mac >= TFC_MAC_VRFY && ctr_mode < TFC_MODE_OCB)
skein_update(&sk, dstblk, ldone);
- if (do_mac == TFC_MAC_JUST_VRFY) goto _nowrite;
+ if (do_mac >= TFC_MAC_JUST_VRFY) goto _nowrite;
pblk = dstblk;
lrem = ldone;
ldone = 0;
-_wagain: lio = write(dfd, pblk, lrem);
+_wagain: lio = xwrite(dfd, pblk, lrem);
if (lio != NOSIZE) ldone += lio;
else xerror(NO, NO, NO, "%s", dstfname);
if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
lrem -= lio;
goto _wagain;
}
+ total_written_dst += ldone;
_nowrite: total_processed_dst += ldone;
delta_processed += ldone;
- if (maxlen != NOFSIZE && total_processed_src >= maxlen) break;
+ if (maxlen != NOFSIZE && total_processed_src >= maxlen) {
+ do_stop = YES;
+ break;
+ }
}
- if (do_stop == TFC_STOP_FULL) goto _nomac;
-
errno = 0;
if (do_mac >= TFC_MAC_VRFY) {
if (!do_mac_file) {
pblk = macvrfy;
ldone = 0;
lrem = lblock = TF_FROM_BITS(macbits);
-_macragain: lio = read(sfd, pblk, lrem);
+ if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
+_macragain: lio = xread(sfd, pblk, lrem);
if (lio != NOSIZE) ldone += lio;
else {
if (errno != EIO && catch_all_errors != YES)
switch (error_action) {
case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _macragain; break;
case TFC_ERRACT_SYNC:
+ case TFC_ERRACT_LSYNC:
xerror(YES, NO, NO, "%s", srcfname);
lio = ldone = lrem = lblock;
memset(macvrfy, 0, lio);
- lseek(sfd, lio, SEEK_CUR);
+ if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+ else lseek(sfd, rdpos + lio, SEEK_SET);
break;
default: xerror(NO, NO, NO, "%s", srcfname); break;
}
if (!strcmp(do_mac_file, "-")) mfd = 0;
else mfd = open(do_mac_file, O_RDONLY | O_LARGEFILE);
if (mfd == -1) xerror(YES, NO, NO, "%s", do_mac_file);
- lio = ldone = read(mfd, tmpdata, sizeof(tmpdata));
+ lio = ldone = xread(mfd, tmpdata, sizeof(tmpdata));
if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file);
if (!memcmp(tmpdata, TFC_ASCII_TFC_MAC_FOURCC, TFC_ASCII_TFC_MAC_FOURCC_LEN)) {
memmove(tmpdata, tmpdata+TFC_ASCII_TFC_MAC_FOURCC_LEN,
tfc_esay("%s: signature is good", progname);
if (verbose) {
if (do_outfmt == TFC_OUTFMT_B64) tfc_printbase64(stderr, macresult, TF_FROM_BITS(macbits), YES);
- else mhexdump(macresult, TF_FROM_BITS(macbits), TF_FROM_BITS(macbits), YES);
+ else mehexdump(macresult, TF_FROM_BITS(macbits), TF_FROM_BITS(macbits), YES);
}
}
+ if (do_mac == TFC_MAC_JUST_VRFY2) {
+ if (verbose) tfc_esay("%s: -u: MAC signature is valid, proceeding with decrypting it again", progname);
+ do_mac = TFC_MAC_DROP;
+ goto _decrypt_again_vrfy2;
+ }
}
else {
- if (quiet == NO) tfc_esay("%s: signature is BAD: "
+ if (quiet == NO) {
+ tfc_esay("%s: signature is BAD: "
"wrong password, key, mode, or file is not signed", progname);
+ if (do_mac == TFC_MAC_JUST_VRFY2) tfc_esay("%s: -u: MAC signature is invalid, not decrypting it again", progname);
+ }
exitcode = 1;
}
pblk = tmpdata;
lio = lrem = TF_FROM_BITS(macbits);
ldone = 0;
-_macwagain: lio = write(dfd, pblk, lrem);
+_macwagain: lio = xwrite(dfd, pblk, lrem);
if (lio != NOSIZE) ldone += lio;
else xerror(NO, NO, NO, "%s", dstfname);
if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
tmpdata[lrem] = '\n';
lrem++;
}
- lio = write(mfd, tmpdata, lrem);
+ lio = xwrite(mfd, tmpdata, lrem);
}
- else lio = write(mfd, tmpdata, TF_FROM_BITS(macbits));
+ else lio = xwrite(mfd, tmpdata, TF_FROM_BITS(macbits));
if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file);
if (do_fsync && fsync(mfd) == -1) xerror(NO, NO, YES, "%s", do_mac_file);
xclose(mfd);
memset(tmpdata, 0, sizeof(tmpdata));
}
-_nomac:
- if (verbose || status_timer || do_stop == TFC_STOP_FULL) print_crypt_status(0);
-
- if (do_preserve_time) fcopy_matime(dfd, &s_stat);
- xclose(sfd);
- xclose(dfd);
+ if (verbose || status_timer || (do_stop == YES && quiet == NO)) print_crypt_status(0);
xexit(exitcode);
return -1;