-E sync: reform logic. Prequery file position, jump over error hole.
[tfcrypt.git] / tfcrypt.c
index dcf9ea98c394e8405cad36b55752c70ea15dfc35..07939a74ddbd8de92cf40b8cfeab539bdb0b0e8a 100644 (file)
--- a/tfcrypt.c
+++ b/tfcrypt.c
@@ -63,8 +63,11 @@ int main(int argc, char **argv)
        if (!isatty(2)) do_statline_dynamic = NO;
 
        opterr = 0;
-       while ((c = getopt(argc, argv, "aU:C:r:K:t:TPkzxc:l:qedn:vV:pwE:O:S:AmM:R:Z:WHD:")) != -1) {
+       while ((c = getopt(argc, argv, "s:aU:C:r:K:t:TPkzxc:l:qedn:vV:pwE:O:S:AmM:R:Z:WHD:")) != -1) {
                switch (c) {
+                       case 's':
+                               saltf = optarg;
+                               break;
                        case 'r':
                                randsource = optarg;
                                break;
@@ -143,6 +146,7 @@ int main(int argc, char **argv)
                                tweakf = optarg;
                                break;
                        case 'T':
+                               tfc_saltsz = 0;
                                do_tfcrypt1 = YES;
                                break;
                        case 'l':
@@ -173,6 +177,8 @@ int main(int argc, char **argv)
                                        error_action = TFC_ERRACT_CONT;
                                else if (!strcmp(optarg, "sync"))
                                        error_action = TFC_ERRACT_SYNC;
+                               else if (!strcmp(optarg, "lsync"))
+                                       error_action = TFC_ERRACT_LSYNC;
                                else xerror(NO, YES, YES, "invalid error action %s specified", optarg);
                                break;
                        case 'O':
@@ -466,6 +472,23 @@ int main(int argc, char **argv)
        errno = 0;
        do_stop = NO;
 
+       if (saltf) {
+               int saltfd;
+
+               memset(tfc_salt, 0, TFC_MAX_SALT);
+               tfc_saltsz = 0;
+               if (!strcasecmp(saltf, "disable")) goto _nosalt;
+
+               if (!strcmp(saltf, "-")) saltfd = 0;
+               else saltfd = open(saltf, O_RDONLY | O_LARGEFILE);
+               if (saltfd == -1) xerror(NO, NO, YES, "%s", saltf);
+               lio = read(saltfd, tfc_salt, TFC_MAX_SALT - TF_FROM_BITS(TFC_KEY_BITS));
+               if (lio == NOSIZE) xerror(NO, NO, YES, "%s", saltf);
+               tfc_saltsz = lio;
+               xclose(saltfd);
+       }
+
+_nosalt:
        if (mackey_opt == TFC_MACKEY_FILE && mackeyf) {
                int mkfd = -1;
                tfc_yesno do_stop;
@@ -482,6 +505,7 @@ int main(int argc, char **argv)
                        pblk = tmpdata;
                        ldone = 0;
                        lrem = lblock = sizeof(tmpdata);
+                       if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(mkfd);
 _mkragain:             lio = read(mkfd, pblk, lrem);
                        if (lio == 0) do_stop = YES;
                        if (lio != NOSIZE) ldone += lio;
@@ -491,10 +515,12 @@ _mkragain:                lio = read(mkfd, pblk, lrem);
                                switch (error_action) {
                                        case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", mackeyf); goto _mkragain; break;
                                        case TFC_ERRACT_SYNC:
+                                       case TFC_ERRACT_LSYNC:
                                                xerror(YES, NO, NO, "%s", mackeyf);
                                                lio = ldone = lrem = lblock;
                                                memset(tmpdata, 0, lio);
-                                               lseek(mkfd, lio, SEEK_CUR);
+                                               if (rdpos == NOFSIZE) lseek(mkfd, lio, SEEK_CUR);
+                                               else lseek(mkfd, rdpos + lio, SEEK_SET);
                                                break;
                                        default: xerror(NO, NO, NO, "%s", mackeyf); break;
                                }
@@ -625,6 +651,7 @@ _nokeyfd:
                pblk = ctr;
                ldone = 0;
                lrem = lblock = ctrsz;
+               if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
 _ctrragain:    lio = read(sfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else {
@@ -633,10 +660,12 @@ _ctrragain:       lio = read(sfd, pblk, lrem);
                        switch (error_action) {
                                case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ctrragain; break;
                                case TFC_ERRACT_SYNC:
+                               case TFC_ERRACT_LSYNC:
                                        xerror(YES, NO, NO, "%s", srcfname);
                                        lio = ldone = lrem = lblock;
                                        memset(ctr, 0, lio);
-                                       lseek(sfd, lio, SEEK_CUR);
+                                       if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+                                       else lseek(sfd, rdpos + lio, SEEK_SET);
                                        break;
                                default: xerror(NO, NO, NO, "%s", srcfname); break;
                        }
@@ -667,6 +696,7 @@ _ctrskip1:
                pblk = key;
 _xts2key:      ldone = 0;
                lrem = lblock = TF_FROM_BITS(TFC_KEY_BITS);
+               if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(kfd);
 _keyragain:    lio = read(kfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else {
@@ -675,10 +705,12 @@ _keyragain:       lio = read(kfd, pblk, lrem);
                        switch (error_action) {
                                case TFC_ERRACT_CONT: xerror(YES, NO, NO, "reading key"); goto _keyragain; break;
                                case TFC_ERRACT_SYNC:
+                               case TFC_ERRACT_LSYNC:
                                        xerror(YES, NO, NO, "reading key");
                                        lio = ldone = lrem = lblock;
                                        memset(key, 0, lio);
-                                       lseek(kfd, lio, SEEK_CUR);
+                                       if (rdpos == NOFSIZE) lseek(kfd, lio, SEEK_CUR);
+                                       else lseek(kfd, rdpos + lio, SEEK_SET);
                                        break;
                                default: xerror(NO, NO, NO, "reading key"); break;
                        }
@@ -786,9 +818,14 @@ _pwdagain: memset(&getps, 0, sizeof(struct getpasswd_state));
                        xerror(NO, NO, YES, "hashing key");
        }
 
-       if (nr_turns > 1 && rawkey == NO) {
-               for (x = 0; x < nr_turns; x++)
+       if (rawkey == NO) {
+               if (tfc_saltsz > 0) {
+                       memcpy(tfc_salt+tfc_saltsz, key, TF_FROM_BITS(TFC_KEY_BITS));
+                       skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, tfc_salt, tfc_saltsz+TF_FROM_BITS(TFC_KEY_BITS));
+               }
+               if (nr_turns > 1) for (x = 0; x < nr_turns; x++)
                        skein(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
+               memset(tfc_salt, 0, TFC_MAX_SALT);
        }
 
        if (ctr_mode == TFC_MODE_XTS && rawkey == NO) {
@@ -860,7 +897,7 @@ _xts2genkey:        if (write(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == -1) xerror(NO,
                        switch (do_outfmt) {
                                case TFC_OUTFMT_B64: tfc_printbase64(stderr, ctr, ctrsz, YES); break;
                                case TFC_OUTFMT_RAW: write(2, ctr, ctrsz); break;
-                               case TFC_OUTFMT_HEX: mhexdump(ctr, ctrsz, ctrsz, YES); break;
+                               case TFC_OUTFMT_HEX: mehexdump(ctr, ctrsz, ctrsz, YES); break;
                        }
                        break;
                case TFC_CTR_RAND: tfc_getrandom(ctr, ctrsz); break;
@@ -943,6 +980,7 @@ _ctrwagain: lio = write(dfd, pblk, lrem);
                pblk = srcblk;
                ldone = 0;
                lrem = lblock = blk_len_adj(maxlen, total_processed_src, blksize);
+               if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
 _ragain:       lio = read(sfd, pblk, lrem);
                if (lio == 0) do_stop = TFC_STOP_BEGAN;
                if (lio != NOSIZE) ldone += lio;
@@ -952,10 +990,12 @@ _ragain:  lio = read(sfd, pblk, lrem);
                        switch (error_action) {
                                case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _ragain; break;
                                case TFC_ERRACT_SYNC:
+                               case TFC_ERRACT_LSYNC:
                                        xerror(YES, NO, NO, "%s", srcfname);
                                        lio = ldone = lrem = lblock;
                                        memset(srcblk, 0, lio);
-                                       lseek(sfd, lio, SEEK_CUR);
+                                       if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+                                       else lseek(sfd, rdpos + lio, SEEK_SET);
                                        break;
                                default: xerror(NO, NO, NO, "%s", srcfname); break;
                        }
@@ -1030,6 +1070,7 @@ _nowrite: total_processed_dst += ldone;
                        pblk = macvrfy;
                        ldone = 0;
                        lrem = lblock = TF_FROM_BITS(macbits);
+                       if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
 _macragain:            lio = read(sfd, pblk, lrem);
                        if (lio != NOSIZE) ldone += lio;
                        else {
@@ -1038,10 +1079,12 @@ _macragain:             lio = read(sfd, pblk, lrem);
                                switch (error_action) {
                                        case TFC_ERRACT_CONT: xerror(YES, NO, NO, "%s", srcfname); goto _macragain; break;
                                        case TFC_ERRACT_SYNC:
+                                       case TFC_ERRACT_LSYNC:
                                                xerror(YES, NO, NO, "%s", srcfname);
                                                lio = ldone = lrem = lblock;
                                                memset(macvrfy, 0, lio);
-                                               lseek(sfd, lio, SEEK_CUR);
+                                               if (rdpos == NOFSIZE) lseek(sfd, lio, SEEK_CUR);
+                                               else lseek(sfd, rdpos + lio, SEEK_SET);
                                                break;
                                        default: xerror(NO, NO, NO, "%s", srcfname); break;
                                }
@@ -1093,7 +1136,7 @@ _macragain:               lio = read(sfd, pblk, lrem);
                                tfc_esay("%s: signature is good", progname);
                                if (verbose) {
                                        if (do_outfmt == TFC_OUTFMT_B64) tfc_printbase64(stderr, macresult, TF_FROM_BITS(macbits), YES);
-                                       else mhexdump(macresult, TF_FROM_BITS(macbits), TF_FROM_BITS(macbits), YES);
+                                       else mehexdump(macresult, TF_FROM_BITS(macbits), TF_FROM_BITS(macbits), YES);
                                }
                        }
                }