-u: like -m, but decrypt to verify MAC, see if it's valid then decrypt to dst.
authorAndrey Rys <rys@lynxlynx.ru>
Sat, 27 Nov 2021 13:24:04 +0000 (14:24 +0100)
committerAndrey Rys <rys@lynxlynx.ru>
Sat, 27 Nov 2021 13:24:04 +0000 (14:24 +0100)
Also adds "written" counter to status line to track actually written bytes to dst.

VERSION
tfc_error.c
tfc_misc.c
tfc_signal.c
tfc_vars.c
tfcrypt.c
tfcrypt.h

diff --git a/VERSION b/VERSION
index e522732c77ec94723e739d22f28df549b0231f5f..a2720097dccb441015beb4f75766b9908ad46f5a 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-38
+39
index 17efe74a443659633b103c507bc1a4b4240a8f2c..2108dc519a02a1822a305355c546ec39fe9526f8 100644 (file)
@@ -269,7 +269,11 @@ void usage(void)
        tfc_say("    -: read a detached MAC signature from stdin,");
        tfc_say("    drop: do not verify attached MAC, if any, and drop it from output.");
        tfc_say("  -m: just verify MAC provided with -M. Do not write output file.");
-       tfc_say("    This option must be specified after -M.");
+       tfc_say("  -u: almost same as -m, but turns on MAC pre-test mode, when verified");
+       tfc_say("    signature enables writing output file. It is useful when decrypting small texts.");
+       tfc_say("    The source must be a seekable file, otherwise this mode will be disabled.");
+       tfc_say("    In this mode, decryption is done twice and verification done once.");
+       tfc_say("    Both -m and -u options must be specified after -M.");
        tfc_say("  -E how: how to behave on I/O errors (both src or dst):");
        tfc_say("    exit: print error if not quiet, then exit,");
        tfc_say("    cont: print error if not quiet, then continue,");
index 06c1a653e7d6a3ac23047288f6e7224e15b83789..57e6b2f67861e7cbd63d0f9c8383c22bebeba161 100644 (file)
@@ -135,7 +135,7 @@ tfc_fsize tfc_fdgetpos(int fd)
        off_t t;
 
        t = lseek(fd, 0L, SEEK_CUR);
-       if (t == -1) return NOFSIZE;
+       if (t == (off_t)-1) return NOFSIZE;
        return (tfc_fsize)t;
 }
 
index 659e9381ec181514d8cddacf785ad79ef898f03c..09c70476f4367c6eaac5e7bf1fe939efd129420e 100644 (file)
@@ -36,8 +36,8 @@ void exit_sigterm(int signal)
 void print_crypt_status(int signal)
 {
        tfc_fsize wr_speed;
-       double seconds, human_totalproc_src, human_totalproc_dst, human_wr_speed;
-       int src_scale_idx, dst_scale_idx, wr_speed_scale;
+       double seconds, human_totalproc_src, human_totalproc_dst, human_totalwrit_dst, human_wr_speed;
+       int src_scale_idx, dst_scale_idx, wri_scale_idx, wr_speed_scale;
        const char *oper_mode, *inplace;
        static tfc_yesno last;
 
@@ -64,6 +64,7 @@ void print_crypt_status(int signal)
        wr_speed = delta_processed / seconds;
        tfc_describescale(total_processed_src, &human_totalproc_src, &src_scale_idx);
        tfc_describescale(total_processed_dst, &human_totalproc_dst, &dst_scale_idx);
+       tfc_describescale(total_written_dst, &human_totalwrit_dst, &wri_scale_idx);
        tfc_describescale(wr_speed, &human_wr_speed, &wr_speed_scale);
 
        if (bench_timer) {
@@ -102,11 +103,13 @@ void print_crypt_status(int signal)
                        wr_speed, human_wr_speed, tfc_getscale(wr_speed_scale), tfc_format_time(total_time));
                else tfc_nfsay(stderr, "%s%s: read: %llu (%.2f%s),"
                        " %s %s %llu (%.2f%s) bytes,"
+                       " written %llu (%.2f%s) bytes,"
                        " (%llu (%.2f%s) B/s), time %s",
                        inplace, progname,
                        total_processed_src, human_totalproc_src, tfc_getscale(src_scale_idx),
                        tfc_modename(ctr_mode), oper_mode,
                        total_processed_dst, human_totalproc_dst, tfc_getscale(dst_scale_idx),
+                       total_written_dst, human_totalwrit_dst, tfc_getscale(wri_scale_idx),
                        wr_speed, human_wr_speed, tfc_getscale(wr_speed_scale), tfc_format_time(total_time));
        }
 
index 1a65ac331968261d16e3bfe983bcda068823090b..359c7e1e1860a13e924a25f6447408502ac7916c 100644 (file)
@@ -42,7 +42,7 @@ tfc_byte tmpdata[TFC_TMPSIZE];
 char *randsource = TFC_DEFAULT_RANDSOURCE;
 
 tfc_fsize iseek_blocks, iseek, oseek, maxlen = NOFSIZE, ftrunc_dfd = NOFSIZE;
-tfc_fsize total_processed_src, total_processed_dst;
+tfc_fsize total_processed_src, total_processed_dst, total_written_dst;
 tfc_fsize delta_processed;
 tfc_fsize genrandom_nr_bytes, genzero_nr_bytes;
 tfc_fsize rdpos = NOFSIZE;
index 83f6c69869a689b2505b691abf8b07c92dc2cca1..6ac7bdceb4da6879c98df6f6483e4cf4d3026559 100644 (file)
--- a/tfcrypt.c
+++ b/tfcrypt.c
@@ -28,6 +28,8 @@
 
 #include "tfcrypt.h"
 
+static tfc_byte svctr[TF_BLOCK_SIZE];
+
 static int getps_filter(struct getpasswd_state *getps, char chr, size_t pos)
 {
        if (chr == '\x03') {
@@ -113,6 +115,7 @@ int main(int argc, char **argv)
        double td;
        char *s, *d, *t, *stoi;
        size_t x, n;
+       tfc_fsize rwd;
 
        progname = basename(argv[0]);
 
@@ -135,7 +138,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:S:AmuM:R:Z:WHD:")) != -1) {
                switch (c) {
                        case 'L':
                                read_defaults(optarg, NO);
@@ -501,9 +504,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':
@@ -1024,6 +1029,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) {
@@ -1106,6 +1112,24 @@ _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", 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) {
@@ -1175,7 +1199,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,6 +1213,7 @@ _wagain:  lio = xwrite(dfd, pblk, lrem);
                        lrem -= lio;
                        goto _wagain;
                }
+               total_written_dst += ldone;
 _nowrite:      total_processed_dst += ldone;
                delta_processed += ldone;
 
@@ -1270,10 +1295,18 @@ _macragain:             lio = xread(sfd, pblk, lrem);
                                        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;
                }
 
index db11b1df6ffed60782c3b528dbde90b3a747dde8..90f53700325e89e16a5176be33e9d811129c61b0 100644 (file)
--- a/tfcrypt.h
+++ b/tfcrypt.h
@@ -139,7 +139,7 @@ extern tfc_byte macvrfy[SKEIN_DIGEST_SIZE], macresult[SKEIN_DIGEST_SIZE];
 extern tfc_byte tmpdata[TFC_TMPSIZE];
 extern char *randsource;
 extern tfc_fsize iseek_blocks, iseek, oseek, maxlen, ftrunc_dfd;
-extern tfc_fsize total_processed_src, total_processed_dst;
+extern tfc_fsize total_processed_src, total_processed_dst, total_written_dst;
 extern tfc_fsize delta_processed;
 extern tfc_fsize genrandom_nr_bytes, genzero_nr_bytes;
 extern tfc_fsize rdpos;
@@ -219,7 +219,7 @@ enum { NO, YES };
 
 enum { TFC_ERRACT_EXIT, TFC_ERRACT_CONT, TFC_ERRACT_SYNC, TFC_ERRACT_LSYNC };
 enum { TFC_DO_PLAIN, TFC_DO_ENCRYPT, TFC_DO_DECRYPT };
-enum { TFC_MAC_DROP = -1, TFC_MAC_SIGN = 1, TFC_MAC_VRFY, TFC_MAC_JUST_VRFY };
+enum { TFC_MAC_DROP = -1, TFC_MAC_SIGN = 1, TFC_MAC_VRFY, TFC_MAC_JUST_VRFY, TFC_MAC_JUST_VRFY2 };
 enum { TFC_MACKEY_RAWKEY = 1, TFC_MACKEY_PASSWORD, TFC_MACKEY_FILE };
 enum { TFC_RAWKEY_KEYFILE = 1, TFC_RAWKEY_ASKSTR, TFC_RAWKEY_ASKHEX };
 enum { TFC_OUTFMT_HEX = 1, TFC_OUTFMT_B64, TFC_OUTFMT_RAW };