51 broke -E logic completely, rewise it
[tfcrypt.git] / tfcrypt.c
index bad1d4372c1f55f9f30b2d6809a7687b1ad20325..590cb33d2fa4ea2ae104a371ce862c4c8fde716a 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:gj")) != -1) {
                switch (c) {
                        case 'L':
                                read_defaults(optarg, NO);
@@ -168,6 +175,14 @@ _baddfname:
                        case 'r':
                                randsource = optarg;
                                break;
+                       case 'j':
+                       case 'g':
+                               if (c == 'j') ctr_mode = TFC_MODE_CTR;
+                               else if (c == 'g') ctr_mode = TFC_MODE_STREAM;
+                               if (do_edcrypt == TFC_DO_DECRYPT) counter_opt = TFC_CTR_HEAD;
+                               else if (do_edcrypt == TFC_DO_ENCRYPT) counter_opt = TFC_CTR_RAND;
+                               else xerror(NO, YES, YES, "plain mode was selected with -%c, cannot continue", c);
+                               break;
                        case 'c':
                                if (!strcasecmp(optarg, "show"))
                                        counter_opt = TFC_CTR_SHOW;
@@ -209,6 +224,8 @@ _baddfname:
                                        ctr_mode = TFC_MODE_STREAM;
                                else if (!strcasecmp(optarg, "cbc"))
                                        ctr_mode = TFC_MODE_CBC;
+                               else if (!strcasecmp(optarg, "pcbc"))
+                                       ctr_mode = TFC_MODE_PCBC;
                                else if (!strcasecmp(optarg, "ecb"))
                                        ctr_mode = TFC_MODE_ECB;
                                else if (!strcasecmp(optarg, "xts"))
@@ -216,9 +233,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;
@@ -402,7 +424,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",
@@ -472,7 +494,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",
@@ -621,7 +643,6 @@ _baddfname:
                                break;
                        case 'q':
                                quiet = YES;
-                               xexit_no_nl = YES;
                                verbose = NO;
                                do_full_hexdump = NO;
                                status_timer = 0;
@@ -673,9 +694,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;
@@ -770,15 +790,23 @@ _mkragain:                lio = xread(mkfd, pblk, lrem);
        || !memcmp(progname+5, "sum", 3)
        || !memcmp(progname+6, "sum", 3)))))
                do_sksum(progname, argv+optind);
-       if (!strcmp(progname, "tfbase64")) do_edbase64(argv+optind);
+       if (!strcmp(progname, "base64")) do_edbase64(argv+optind);
 
        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);
 
@@ -878,7 +906,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));
 
@@ -1176,23 +1204,27 @@ _decrypt_again_vrfy2:
                }
                total_processed_src = rwd;
                memcpy(ctr, svctr, TF_BLOCK_SIZE);
+               if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr);
                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;
                        }
@@ -1210,8 +1242,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;
                        }
@@ -1230,6 +1262,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);
@@ -1246,10 +1285,17 @@ _ragain:        lio = xread(sfd, pblk, lrem);
                        tf_cbc_encrypt(key, ctr, dstblk, srcblk, ldone);
                else if (ctr_mode == TFC_MODE_CBC && do_edcrypt == TFC_DO_DECRYPT)
                        tf_cbc_decrypt(key, ctr, dstblk, srcblk, ldone);
+               else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_ENCRYPT)
+                       tf_pcbc_encrypt(key, ctr, dstblk, srcblk, ldone);
+               else if (ctr_mode == TFC_MODE_PCBC && do_edcrypt == TFC_DO_DECRYPT)
+                       tf_pcbc_decrypt(key, ctr, dstblk, srcblk, ldone);
 
                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;
 
@@ -1340,6 +1386,7 @@ _macragain:               lio = xread(sfd, pblk, lrem);
                else if (ctr_mode == TFC_MODE_XTS) tf_xts_decrypt(key, xtskey, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits), xtsblocks);
                else if (ctr_mode == TFC_MODE_ECB) tf_ecb_decrypt(key, tmpdata, macvrfy, TF_FROM_BITS(macbits));
                else if (ctr_mode == TFC_MODE_CBC) tf_cbc_decrypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits));
+               else if (ctr_mode == TFC_MODE_PCBC) tf_pcbc_decrypt(key, ctr, tmpdata, macvrfy, TF_FROM_BITS(macbits));
 
                if (!memcmp(tmpdata, macresult, TF_FROM_BITS(macbits))) {
                        if (quiet == NO) {
@@ -1377,6 +1424,7 @@ _shortmac:        memset(macvrfy, 0, sizeof(macvrfy));
                else if (ctr_mode == TFC_MODE_XTS) tf_xts_encrypt(key, xtskey, ctr, tmpdata, macresult, TF_FROM_BITS(macbits), xtsblocks);
                else if (ctr_mode == TFC_MODE_ECB) tf_ecb_encrypt(key, tmpdata, macresult, TF_FROM_BITS(macbits));
                else if (ctr_mode == TFC_MODE_CBC) tf_cbc_encrypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits));
+               else if (ctr_mode == TFC_MODE_PCBC) tf_pcbc_encrypt(key, ctr, tmpdata, macresult, TF_FROM_BITS(macbits));
                memset(macresult, 0, sizeof(macresult));
 
                if (!do_mac_file) {
@@ -1425,7 +1473,7 @@ _macwagain:               lio = xwrite(dfd, pblk, lrem);
        }
        else if (do_mac == TFC_MAC_DROP2) total_processed_src += SKEIN_DIGEST_SIZE;
 
-       if (verbose || status_timer || (do_stop == YES && quiet == NO)) print_crypt_status(0);
+       if (verbose || status_timer || (do_stop == YES && quiet == NO)) print_crypt_status(TFC_SIGLAST);
 
        xexit(exitcode);
        return -1;