Also adds "written" counter to status line to track actually written bytes to dst.
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,");
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;
}
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;
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) {
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));
}
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;
#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') {
double td;
char *s, *d, *t, *stoi;
size_t x, n;
+ tfc_fsize rwd;
progname = basename(argv[0]);
}
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);
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':
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) {
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) {
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;
lrem -= lio;
goto _wagain;
}
+ total_written_dst += ldone;
_nowrite: total_processed_dst += ldone;
delta_processed += ldone;
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;
}
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;
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 };