From b0637473e28d682b2ec870dd62cc05eb749842d0 Mon Sep 17 00:00:00 2001 From: Andrey Rys Date: Sun, 28 Aug 2022 15:45:24 +0200 Subject: [PATCH] -X: add simple XOR mode (embedded xor tool) --- VERSION | 2 +- tfc_error.c | 19 ++++++++++++++- tfc_misc.c | 1 + tfc_random.c | 4 ++-- tfc_signal.c | 1 + tfcrypt.c | 68 ++++++++++++++++++++++++++++++++++++++-------------- tfcrypt.h | 2 +- 7 files changed, 74 insertions(+), 23 deletions(-) diff --git a/VERSION b/VERSION index 3fdcd7c..38b10c1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -67 +68 diff --git a/tfc_error.c b/tfc_error.c index 6f994ef..953ba07 100644 --- a/tfc_error.c +++ b/tfc_error.c @@ -114,7 +114,7 @@ void usage(void) if (optopt == 'V') { tfc_say("tfcrypt toolkit, version %s.", _TFCRYPT_VERSION); - if (ctr_mode != TFC_MODE_PLAIN) { + if (do_edcrypt != TFC_DO_PLAIN) { char shash[64]; hash_defaults(shash, sizeof(shash)); @@ -210,6 +210,22 @@ void usage(void) tfc_say("no error checking is performed."); tfc_say("\n"); } + else if (!strcmp(progname, "xor")) { + is_embedded_prog = YES; + tfc_say("usage: %s [sourceX] [sourceY] [output]", progname); + tfc_say("\n"); + tfc_say("tfcrypt embedded high performance XOR tool."); + tfc_say("It does XOR (multiply modulo 2) of each byte from sourceX"); + tfc_say("each byte of sourceY and writes output."); + tfc_say("If filenames omitted, it is assumed to operate over"); + tfc_say("standard in to standard out."); + tfc_say("If any of source files is shorter than another,"); + tfc_say("then output is truncated to length of the shortest one."); + tfc_say("\n"); + tfc_say("No error checking is performed."); + tfc_say("Please use iotool options there."); + tfc_say("\n"); + } else if (!strcmp(progname, "tfbench")) { is_embedded_prog = YES; tfc_say("usage: %s seconds", progname); @@ -364,6 +380,7 @@ void usage(void) tfc_say(" xctr=val: specify size in bytes of initial counter prepended or read."); tfc_say(" fullkey: occupy tweak space by key space, extending key size by 256 bits."); tfc_say(" -P: plain IO mode: disable encryption/decryption code at all."); + tfc_say(" -X: XOR IO mode: same as -P but do XOR of two streams."); tfc_say("\n"); tfc_say("Default is to ask for password, then encrypt stdin into stdout."); tfc_say("Some cmdline parameters may be mutually exclusive, or they can"); diff --git a/tfc_misc.c b/tfc_misc.c index 5902896..2aa58df 100644 --- a/tfc_misc.c +++ b/tfc_misc.c @@ -107,6 +107,7 @@ tfc_yesno tfc_is_freestream(int mode) { switch (mode) { case TFC_MODE_PLAIN: + case TFC_MODE_XOR: case TFC_MODE_STREAM: return YES; } diff --git a/tfc_random.c b/tfc_random.c index 0a529d4..99612d3 100644 --- a/tfc_random.c +++ b/tfc_random.c @@ -150,7 +150,7 @@ void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes) xerror(ignore_seek_errors, NO, NO, "%s: seek failed", foutname); } - if (ctr_mode == TFC_MODE_PLAIN) memset(srcblk, 0, sizeof(srcblk)); + if (do_edcrypt == TFC_DO_PLAIN) memset(srcblk, 0, sizeof(srcblk)); if (verbose) tfc_nfsay(stderr, "%s: writing %lld bytes to %s ... ", tfc_format_pid(progname), nrbytes, foutname); @@ -162,7 +162,7 @@ void gen_write_bytes(const char *foutname, tfc_fsize offset, tfc_fsize nrbytes) pblk = srcblk; lblock = lrem = blk_len_adj(nrbytes, total_processed_src, blksize); - if (ctr_mode != TFC_MODE_PLAIN) tfc_getrandom(srcblk, lblock); + if (do_edcrypt != TFC_DO_PLAIN) tfc_getrandom(srcblk, lblock); if (error_action == TFC_ERRACT_SYNC) wrpos = tfc_fdgetpos(fd); _wagain: lio = xwrite(fd, pblk, lrem); diff --git a/tfc_signal.c b/tfc_signal.c index 1e02534..aaacb2b 100644 --- a/tfc_signal.c +++ b/tfc_signal.c @@ -66,6 +66,7 @@ void print_crypt_status(int signal) case TFC_DO_DECRYPT: oper_mode = "decrypted"; break; default: if (ctr_mode == TFC_MODE_PLAIN) oper_mode = "written"; + else if (ctr_mode == TFC_MODE_XOR) oper_mode = "xored"; else if (ctr_mode == TFC_MODE_SKSUM) oper_mode = "hashed"; else oper_mode = NULL; break; diff --git a/tfcrypt.c b/tfcrypt.c index 45438cb..a540db4 100644 --- a/tfcrypt.c +++ b/tfcrypt.c @@ -130,6 +130,7 @@ static void say_hint(const void *data, size_t szdata, const char *prompt) int main(int argc, char **argv) { + tfc_yesno flipfd; int c; double td; char *s, *d, *t, *stoi; @@ -152,12 +153,18 @@ _baddfname: if (!strcmp(progname, "iotool")) { do_edcrypt = TFC_DO_PLAIN; - password = YES; ctr_mode = TFC_MODE_PLAIN; } + if (!strcmp(progname, "xor")) { + do_edcrypt = TFC_DO_PLAIN; + ctr_mode = TFC_MODE_XOR; + /* xor: default to stdin if invoked without args */ + kfd = 0; + } + opterr = 0; - 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) { + while ((c = getopt(argc, argv, "L:s:aU:C:r:K:t:PXkzxc:l:qedn:vV:pwE:o:O:S:AmuM:R:Z:WHD:")) != -1) { switch (c) { case 'L': read_defaults(optarg, NO); @@ -218,9 +225,14 @@ _baddfname: else xerror(NO, YES, YES, "%s: invalid mode of operation", optarg); break; case 'P': + case 'X': do_edcrypt = TFC_DO_PLAIN; - password = YES; - ctr_mode = TFC_MODE_PLAIN; + if (c == 'X') { + ctr_mode = TFC_MODE_XOR; + /* xor: default to stdin if invoked without args */ + kfd = 0; + } + else ctr_mode = TFC_MODE_PLAIN; break; case 'e': if (do_edcrypt != TFC_DO_PLAIN) do_edcrypt = TFC_DO_ENCRYPT; @@ -404,7 +416,7 @@ _baddfname: "%s: invalid iseek value", s); } else iseek = tfc_modifysize(iseek, strchr(s, ':')); - if (ctr_mode != TFC_MODE_PLAIN && iseek % TF_BLOCK_SIZE) + if (do_edcrypt != TFC_DO_PLAIN && iseek % TF_BLOCK_SIZE) xerror(NO, YES, YES, "%s: not round to TF block size " "of %u bytes", @@ -474,7 +486,7 @@ _baddfname: "%s: invalid iseek value", s); } else iseek = tfc_modifysize(iseek, strchr(s, ':')); - if (ctr_mode != TFC_MODE_PLAIN && iseek % TF_BLOCK_SIZE) + if (do_edcrypt != TFC_DO_PLAIN && iseek % TF_BLOCK_SIZE) xerror(NO, YES, YES, "%s: not round to TF block size " "of %u bytes", @@ -675,9 +687,8 @@ _baddfname: 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 (ctr_mode == TFC_MODE_PLAIN - && (do_edcrypt || do_mac || rawkey - || mackey_opt || counter_opt || counter_file)) + if (do_edcrypt == TFC_DO_PLAIN + && (do_mac || saltf || rawkey || mackey_opt || counter_opt || counter_file)) xerror(NO, YES, YES, "Encryption facility is disabled when in plain IO mode."); errno = 0; @@ -777,10 +788,18 @@ _mkragain: lio = xread(mkfd, pblk, lrem); idx = optind; if (argv[idx]) { - if (password || rawkey > TFC_RAWKEY_KEYFILE) goto _nokeyfd; + if ((do_edcrypt == TFC_DO_PLAIN && ctr_mode == TFC_MODE_PLAIN) + || password + || rawkey > TFC_RAWKEY_KEYFILE) goto _nokeyfd; if (!strcmp(argv[idx], "-")) kfd = 0; else kfd = xopen(argv[idx], O_RDONLY | O_LARGEFILE); + if (do_edcrypt == TFC_DO_PLAIN && ctr_mode == TFC_MODE_XOR) { + /* out: don't erase kfname if xor */ + idx++; + goto _nokeyfd; + } + lio = strnlen(argv[idx], PATH_MAX); memset(argv[idx], '*', lio); @@ -880,7 +899,7 @@ _ctrskip1: xerror(ignore_seek_errors, NO, NO, "%s: seek failed", srcfname); } - if (ctr_mode == TFC_MODE_PLAIN) goto _plain; + if (do_edcrypt == TFC_DO_PLAIN) goto _plain; if (verbose) tfc_esay("%s: hashing password", tfc_format_pid(progname)); @@ -1181,20 +1200,23 @@ _decrypt_again_vrfy2: memset(svctr, 0, TF_BLOCK_SIZE); } +#define FLFD(x, y) (flipfd ? y : x) _nodecrypt_again_vrfy2: loopcnt = 1; errno = 0; do_stop = NO; + flipfd = NO; while (1) { if (do_stop) break; + if (ctr_mode == TFC_MODE_XOR) flipfd = NO; pblk = srcblk; - ldone = 0; +_nextblk: ldone = 0; 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 (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(FLFD(sfd, kfd)); +_ragain: lio = xread(FLFD(sfd, kfd), pblk, lrem); if (lio == 0) { - if ((do_read_loops != 0 && sfd != 0) && (loopcnt < do_read_loops)) { - lseek(sfd, 0L, SEEK_SET); + if ((do_read_loops != 0 && FLFD(sfd, kfd) != 0) && (loopcnt < do_read_loops)) { + lseek(FLFD(sfd, kfd), 0L, SEEK_SET); loopcnt++; goto _ragain; } @@ -1212,8 +1234,8 @@ _ragain: lio = xread(sfd, pblk, lrem); xerror(YES, NO, NO, "%s", srcfname); lio = ldone = lrem = lblock; memset(srcblk, 0, lio); - if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR); - else lseek(sfd, rdpos + lio, SEEK_SET); + if (rdpos == NOFSIZE) lseek(FLFD(sfd, kfd), lio, SEEK_CUR); + else lseek(FLFD(sfd, kfd), rdpos + lio, SEEK_SET); break; default: xerror(NO, NO, NO, "%s", srcfname); break; } @@ -1232,6 +1254,13 @@ _ragain: lio = xread(sfd, pblk, lrem); memset(srcblk+orig, 0, sizeof(srcblk)-orig); } + if (ctr_mode == TFC_MODE_XOR && flipfd == NO) { + if (do_stop) blksize = ldone; + flipfd = YES; + pblk = dstblk; + goto _nextblk; + } + if (do_mac == TFC_MAC_SIGN) skein_update(&sk, srcblk, ldone); if (ctr_mode == TFC_MODE_CTR) tf_ctr_crypt(key, ctr, dstblk, srcblk, ldone); @@ -1256,6 +1285,9 @@ _ragain: lio = xread(sfd, pblk, lrem); else if (ctr_mode == TFC_MODE_PLAIN) memcpy(dstblk, srcblk, ldone); + else if (ctr_mode == TFC_MODE_XOR) + xor_block(dstblk, srcblk, ldone); + if (do_mac >= TFC_MAC_VRFY) skein_update(&sk, dstblk, ldone); if (do_mac >= TFC_MAC_JUST_VRFY) goto _nowrite; diff --git a/tfcrypt.h b/tfcrypt.h index ad12ef8..2dd2c68 100644 --- a/tfcrypt.h +++ b/tfcrypt.h @@ -233,7 +233,7 @@ 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 }; enum { - TFC_MODE_SKSUM = -2, TFC_MODE_PLAIN = -1, TFC_MODE_CTR = 1, + TFC_MODE_SKSUM = -3, TFC_MODE_XOR = -2, TFC_MODE_PLAIN = -1, TFC_MODE_CTR = 1, TFC_MODE_STREAM, TFC_MODE_XTS, TFC_MODE_ECB, TFC_MODE_CBC, TFC_MODE_PCBC }; enum { TFC_CTR_SHOW = 1, TFC_CTR_HEAD, TFC_CTR_RAND, TFC_CTR_ZERO, TFC_CTR_SSET }; -- 2.31.1