X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=tfcrypt.c;h=e5ac31a33f99f600324ae2dbb8f13b52ceb65041;hb=8cf1129abf5f42bd57fe0f6f0c5308d425b95027;hp=83f6c69869a689b2505b691abf8b07c92dc2cca1;hpb=a874fa08a172c1d5006d15d05e494e1b9fbda211;p=tfcrypt.git diff --git a/tfcrypt.c b/tfcrypt.c index 83f6c69..e5ac31a 100644 --- a/tfcrypt.c +++ b/tfcrypt.c @@ -28,6 +28,23 @@ #include "tfcrypt.h" +static tfc_byte svctr[TF_BLOCK_SIZE]; +static tfc_fsize rwd, do_read_loops, loopcnt; + +static void open_log(const char *logfile) +{ + int fd; + + if (!strcmp(logfile, "-")) return; + + 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') { @@ -114,6 +131,7 @@ int main(int argc, char **argv) char *s, *d, *t, *stoi; size_t x, n; + progpid = getpid(); progname = basename(argv[0]); if (!isatty(2)) do_statline_dynamic = NO; @@ -135,7 +153,7 @@ _baddfname: } opterr = 0; - while ((c = getopt(argc, argv, "L:s:aU:C:r:K:t:Pkzxc: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); @@ -282,6 +300,9 @@ _baddfname: 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))) { @@ -314,6 +335,16 @@ _baddfname: do_full_key = YES; else if (!strcmp(s, "showsecrets")) show_secrets = YES; + else if (!strcmp(s, "finished")) + show_when_done = YES; + else if (!strcmp(s, "pid")) + show_pid = YES; + else if (!strncmp(s, "readloops", 9) && *(s+9) == '=') { + do_read_loops = tfc_humanfsize(s+10, &stoi); + if (!str_empty(stoi)) do_read_loops = NOSIZE; + } + 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); @@ -501,9 +532,11 @@ _baddfname: 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': @@ -547,6 +580,7 @@ _baddfname: break; case 'q': quiet = YES; + xexit_no_nl = YES; verbose = NO; do_full_hexdump = NO; status_timer = 0; @@ -739,12 +773,6 @@ _nokeyfd: } if (sfd == -1) xerror(NO, NO, YES, "%s", argv[idx]); - if (do_edcrypt == TFC_DO_DECRYPT && do_mac != NO && maxlen != NOFSIZE) { - if (verbose) tfc_esay("%s: disabling signature verification on " - "requested partial decryption.", progname); - do_mac = NO; - } - if ((do_mac >= TFC_MAC_VRFY || do_mac == TFC_MAC_DROP) && !do_mac_file) { maxlen = tfc_fdsize(sfd); if (maxlen == NOFSIZE) @@ -816,7 +844,7 @@ _ctrskip1: if (ctr_mode == TFC_MODE_PLAIN) goto _plain; - if (verbose) tfc_esay("%s: hashing password", progname); + if (verbose) tfc_esay("%s: hashing password", tfc_format_pid(progname)); if (rawkey == TFC_RAWKEY_KEYFILE) { tfc_yesno xtskeyset = NO; @@ -974,9 +1002,9 @@ _pwdagain: memset(&getps, 0, sizeof(struct getpasswd_state)); _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); - tfc_esay("%s: rawkey written to %s.", progname, genkeyf); - tfc_esay("%s: Have a nice day!", progname); + tfc_esay("%s: password hashing done", tfc_format_pid(progname)); + tfc_esay("%s: rawkey written to %s.", tfc_format_pid(progname), genkeyf); + tfc_esay("%s: Have a nice day!", tfc_format_pid(progname)); } if (ctr_mode == TFC_MODE_XTS) { @@ -992,17 +1020,11 @@ _xts2genkey: if (xwrite(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == NOSIZE) xerro xexit(0); } - if (iseek_blocks && (do_edcrypt == TFC_DO_DECRYPT && do_mac != NO)) { - if (verbose) tfc_esay("%s: disabling signature verification on " - "requested partial decryption.", progname); - do_mac = NO; - } - if (do_mac != NO) { if (mackey_opt == TFC_MACKEY_RAWKEY) skein(mackey, TF_MAX_BITS, key, key, TF_FROM_BITS(TFC_KEY_BITS)); if (ctr_mode < TFC_MODE_OCB) { if (verbose) tfc_esay("%s: doing MAC calculation, processing speed " - "will be slower.", progname); + "will be slower.", tfc_format_pid(progname)); if (mackey_opt) skein_init_key(&sk, mackey, macbits); else skein_init(&sk, macbits); } @@ -1024,6 +1046,7 @@ _xts2genkey: if (xwrite(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == NOSIZE) xerro 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); if (counter_opt == TFC_CTR_SHOW) { switch (do_outfmt) { @@ -1039,7 +1062,7 @@ _ctrskip2: xclose(kfd); kfd = -1; } - if (verbose) tfc_esay("%s: password hashing done", progname); + if (verbose) tfc_esay("%s: password hashing done", tfc_format_pid(progname)); if (overwrite_source && srcfname) argv[idx] = srcfname; @@ -1065,9 +1088,8 @@ _plain: 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; @@ -1076,11 +1098,14 @@ _plain: 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)); @@ -1106,6 +1131,25 @@ _ctrwagain: lio = xwrite(dfd, pblk, lrem); 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", tfc_format_pid(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: + loopcnt = 1; errno = 0; do_stop = NO; while (1) { @@ -1115,7 +1159,15 @@ _ctrwagain: lio = xwrite(dfd, pblk, lrem); lrem = lblock = blk_len_adj(maxlen, total_processed_src, blksize); if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd); _ragain: lio = xread(sfd, pblk, lrem); - if (lio == 0) do_stop = YES; + if (lio == 0) { + if ((do_read_loops != 0 && sfd != 0) && (loopcnt < do_read_loops)) { + lseek(sfd, 0L, SEEK_SET); + loopcnt++; + goto _ragain; + } + + do_stop = YES; + } if (lio != NOSIZE) ldone += lio; else { if (errno != EIO && catch_all_errors != YES) @@ -1175,7 +1227,7 @@ _ragain: lio = xread(sfd, pblk, lrem); 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; @@ -1189,10 +1241,14 @@ _wagain: lio = xwrite(dfd, pblk, lrem); 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; + } } errno = 0; @@ -1247,7 +1303,7 @@ _macragain: lio = xread(sfd, pblk, lrem); if (ldone < TF_FROM_BITS(macbits)) { if (quiet == NO) tfc_esay("%s: short signature (%zu), " - "not verifying", progname, ldone); + "not verifying", tfc_format_pid(progname), ldone); exitcode = 1; goto _shortmac; } @@ -1264,16 +1320,24 @@ _macragain: lio = xread(sfd, pblk, lrem); if (!memcmp(tmpdata, macresult, TF_FROM_BITS(macbits))) { if (quiet == NO) { - tfc_esay("%s: signature is good", progname); + tfc_esay("%s: signature is good", tfc_format_pid(progname)); if (verbose) { if (do_outfmt == TFC_OUTFMT_B64) tfc_printbase64(stderr, macresult, 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", tfc_format_pid(progname)); + do_mac = TFC_MAC_DROP; + goto _decrypt_again_vrfy2; + } } else { - if (quiet == NO) tfc_esay("%s: signature is BAD: " - "wrong password, key, mode, or file is not signed", progname); + if (quiet == NO) { + tfc_esay("%s: signature is BAD: " + "wrong password, key, mode, or file is not signed", tfc_format_pid(progname)); + if (do_mac == TFC_MAC_JUST_VRFY2) tfc_esay("%s: -u: MAC signature is invalid, not decrypting it again", tfc_format_pid(progname)); + } exitcode = 1; } @@ -1339,15 +1403,7 @@ _macwagain: lio = xwrite(dfd, pblk, lrem); memset(tmpdata, 0, sizeof(tmpdata)); } - if (verbose || status_timer || do_stop == YES) print_crypt_status(0); - - if (do_preserve_time) fcopy_matime(dfd, &s_stat); - xclose(sfd); - if (do_ftrunc > TFC_NO_FTRUNC) { - if (do_ftrunc == TFC_FTRUNC_TAIL) ftrunc_dfd = total_processed_dst; - if (ftruncate(dfd, (off_t)ftrunc_dfd) == -1) xerror(YES, NO, YES, "ftruncate(%d)", dfd); - } - xclose(dfd); + if (verbose || status_timer || (do_stop == YES && quiet == NO)) print_crypt_status(0); xexit(exitcode); return -1;