-X: add simple XOR mode (embedded xor tool)
authorAndrey Rys <rys@lynxlynx.ru>
Sun, 28 Aug 2022 13:45:24 +0000 (15:45 +0200)
committerAndrey Rys <rys@lynxlynx.ru>
Sun, 28 Aug 2022 13:45:24 +0000 (15:45 +0200)
VERSION
tfc_error.c
tfc_misc.c
tfc_random.c
tfc_signal.c
tfcrypt.c
tfcrypt.h

diff --git a/VERSION b/VERSION
index 3fdcd7c44cb1791f45e7386a8f230e018fd7e052..38b10c1b2badd802b554ecc944a7a40c5f055d47 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-67
+68
index 6f994ef7daacc28d9bc675d6058386b2b478de44..953ba0725a648f1079be4d5cd0ac2ec76f63a5c6 100644 (file)
@@ -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");
index 5902896e82c5b5b2352cfd2b7d75a580b3b2ec3d..2aa58df4b5fd46ea9d579f3be3e4cafb85067e0f 100644 (file)
@@ -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;
        }
 
index 0a529d401b53410f08ef97d436a6fc4b578ab1f6..99612d34d3c01d131feb155fd8e8fbf933614ca5 100644 (file)
@@ -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);
index 1e025349a52c70e73a6c945d1ac141353ad0bdcc..aaacb2bb8191c9dbd28785b384547d9b7e756529 100644 (file)
@@ -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;
index 45438cb2bde7dc46cdc05ea0fba5b20d7ca7eebf..a540db4b77e7586fb00f351b682244e2ce7f1ca7 100644 (file)
--- 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;
 
index ad12ef8a941f3417ec7ae3fc6d4d1b3fc9974a34..2dd2c68bef1c5f5b17879114f0290308f2045b75 100644 (file)
--- 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 };