-c zero: assume zero counter value.
[tfcrypt.git] / tfcrypt.c
index 07939a74ddbd8de92cf40b8cfeab539bdb0b0e8a..01173fb691a214f7e666fb0f48552072b4c59756 100644 (file)
--- a/tfcrypt.c
+++ b/tfcrypt.c
@@ -62,9 +62,22 @@ int main(int argc, char **argv)
 
        if (!isatty(2)) do_statline_dynamic = NO;
 
+       s = (char *)srcblk;
+       d = getenv("HOME");
+       if (!d) d = "";
+       n = PATH_MAX > sizeof(srcblk) ? sizeof(srcblk) : PATH_MAX;
+       if (xstrlcpy(s, d, n) >= n) goto _baddfname;
+       if (xstrlcat(s, "/.tfcrypt.defs", n) >= n) goto _baddfname;
+       read_defaults(s, YES);
+_baddfname:
+       memset(s, 0, n);
+
        opterr = 0;
-       while ((c = getopt(argc, argv, "s:aU:C:r:K:t:TPkzxc:l:qedn:vV:pwE:O:S:AmM:R:Z:WHD:")) != -1) {
+       while ((c = getopt(argc, argv, "L:s:aU:C:r:K:t:TPkzxc:l:qedn:vV:pwE:O:S:AmM:R:Z:WHD:")) != -1) {
                switch (c) {
+                       case 'L':
+                               read_defaults(optarg, NO);
+                               break;
                        case 's':
                                saltf = optarg;
                                break;
@@ -78,6 +91,8 @@ int main(int argc, char **argv)
                                        counter_opt = TFC_CTR_HEAD;
                                else if (!strcasecmp(optarg, "rand"))
                                        counter_opt = TFC_CTR_RAND;
+                               else if (!strcasecmp(optarg, "zero"))
+                                       counter_opt = TFC_CTR_ZERO;
                                else counter_file = sksum_hashlist_file = optarg;
                                break;
                        case 'C':
@@ -171,6 +186,10 @@ int main(int argc, char **argv)
                                        catch_all_errors = YES;
                                        break;
                                }
+                               if (!strcmp(optarg, "xseek")) {
+                                       ignore_seek_errors = YES;
+                                       break;
+                               }
                                if (!strcmp(optarg, "exit"))
                                        error_action = TFC_ERRACT_EXIT;
                                else if (!strncmp(optarg, "cont", 4))
@@ -328,13 +347,25 @@ int main(int argc, char **argv)
                                                s += 5;
                                                maxkeylen = tfc_humanfsize(s, &stoi);
                                                if (!str_empty(stoi)) {
-                                                       maxkeylen = (size_t)tfc_fnamesize(s, YES);
-                                                       maxkeylen = (size_t)tfc_modifysize((tfc_fsize)maxkeylen, strchr(s, ':'));
+                                                       maxkeylen = tfc_fnamesize(s, YES);
+                                                       maxkeylen = tfc_modifysize(maxkeylen, strchr(s, ':'));
                                                        if (maxkeylen == NOSIZE)
                                                                xerror(NO, YES, YES,
                                                                "%s: invalid key length value", s);
                                                }
-                                               else maxkeylen = (size_t)tfc_modifysize((tfc_fsize)maxkeylen, strchr(s, ':'));
+                                               else maxkeylen = tfc_modifysize(maxkeylen, strchr(s, ':'));
+                                       }
+                                       else if (!strncmp(s, "okey", 4) && *(s+4) == '=') {
+                                               s += 5;
+                                               keyoffset = tfc_humanfsize(s, &stoi);
+                                               if (!str_empty(stoi)) {
+                                                       keyoffset = tfc_fnamesize(s, YES);
+                                                       keyoffset = tfc_modifysize(keyoffset, strchr(s, ':'));
+                                                       if (keyoffset == NOFSIZE)
+                                                               xerror(NO, YES, YES,
+                                                               "%s: invalid key offset value", s);
+                                               }
+                                               else keyoffset = tfc_modifysize(keyoffset, strchr(s, ':'));
                                        }
                                        else if (!strncmp(s, "xctr", 4) && *(s+4) == '=') {
                                                s += 5;
@@ -482,7 +513,7 @@ int main(int argc, char **argv)
                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));
+               lio = xread(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);
@@ -506,7 +537,7 @@ _nosalt:
                        ldone = 0;
                        lrem = lblock = sizeof(tmpdata);
                        if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(mkfd);
-_mkragain:             lio = read(mkfd, pblk, lrem);
+_mkragain:             lio = xread(mkfd, pblk, lrem);
                        if (lio == 0) do_stop = YES;
                        if (lio != NOSIZE) ldone += lio;
                        else {
@@ -593,7 +624,7 @@ _mkragain:          lio = read(mkfd, pblk, lrem);
                if (!strcmp(tweakf, "-")) twfd = 0;
                else twfd = open(tweakf, O_RDONLY | O_LARGEFILE);
                if (twfd == -1) xerror(NO, NO, YES, "%s", tweakf);
-               lio = ldone = read(twfd, key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_SIZE_UNIT);
+               lio = ldone = xread(twfd, key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_SIZE_UNIT);
                if (lio == NOSIZE) xerror(NO, NO, YES, "%s", tweakf);
                if (ldone < 2*TF_SIZE_UNIT)
                        xerror(NO, NO, YES, "%s: %zu bytes tweak required", tweakf, 2*TF_SIZE_UNIT);
@@ -642,7 +673,7 @@ _nokeyfd:
                if (!strcmp(counter_file, "-")) ctrfd = 0;
                else ctrfd = open(counter_file, O_RDONLY | O_LARGEFILE);
                if (ctrfd == -1) xerror(NO, NO, YES, "%s", counter_file);
-               lio = read(ctrfd, ctr, ctrsz);
+               lio = xread(ctrfd, ctr, ctrsz);
                if (lio == NOSIZE) xerror(NO, NO, YES, "%s", counter_file);
                if (lio < ctrsz) xerror(NO, YES, YES, "counter file is too small (%zu)!", lio);
                xclose(ctrfd);
@@ -652,7 +683,7 @@ _nokeyfd:
                ldone = 0;
                lrem = lblock = ctrsz;
                if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
-_ctrragain:    lio = read(sfd, pblk, lrem);
+_ctrragain:    lio = xread(sfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else {
                        if (errno != EIO && catch_all_errors != YES)
@@ -683,7 +714,7 @@ _ctrskip1:
                if (counter_opt == TFC_CTR_HEAD && ctr_mode != TFC_MODE_ECB)
                        iseek += ctrsz;
                if (lseek(sfd, iseek, SEEK_SET) == -1)
-                       xerror(YES, NO, NO, "%s: seek failed", srcfname);
+                       xerror(ignore_seek_errors, NO, NO, "%s: seek failed", srcfname);
        }
 
        if (ctr_mode == TFC_MODE_PLAIN) goto _plain;
@@ -697,7 +728,7 @@ _ctrskip1:
 _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);
+_keyragain:    lio = xread(kfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else {
                        if (errno != EIO && catch_all_errors != YES)
@@ -814,7 +845,7 @@ _pwdagain:  memset(&getps, 0, sizeof(struct getpasswd_state));
                memset(pwdagain, 0, sizeof(pwdagain));
        }
        else {
-               if (skeinfd(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, kfd, maxkeylen) != YES)
+               if (skeinfd(key, TFC_KEY_BITS, mackey_opt ? mackey : NULL, kfd, keyoffset, maxkeylen) != YES)
                        xerror(NO, NO, YES, "hashing key");
        }
 
@@ -840,7 +871,7 @@ _pwdagain:  memset(&getps, 0, sizeof(struct getpasswd_state));
                if (!strcmp(genkeyf, "-")) krfd = 1;
                else krfd = open(genkeyf, O_WRONLY | O_CREAT | O_LARGEFILE | write_flags, 0666);
                if (krfd == -1) xerror(NO, NO, YES, "%s", genkeyf);
-_xts2genkey:   if (write(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == -1) xerror(NO, NO, YES, "%s", genkeyf);
+_xts2genkey:   if (xwrite(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == NOSIZE) xerror(NO, NO, YES, "%s", genkeyf);
                if (do_fsync && fsync(krfd) == -1) xerror(NO, NO, YES, "%s", genkeyf);
                if (verbose && xtskeyset == NO) {
                        tfc_esay("%s: password hashing done", progname);
@@ -887,7 +918,6 @@ _xts2genkey:        if (write(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == -1) xerror(NO,
                if (!tweakf) skein(key+TF_FROM_BITS(TF_MAX_BITS)+TF_SIZE_UNIT, 2*TF_UNIT_BITS, NULL, key, TF_FROM_BITS(TFC_KEY_BITS));
                tf_key_tweak_compat(key);
        }
-       if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr);
        if (ctr_mode == TFC_MODE_ECB) goto _ctrskip2;
        tfc_data_to_words64(&iseek_blocks, sizeof(iseek_blocks));
        tf_ctr_set(ctr, &iseek_blocks, sizeof(iseek_blocks));
@@ -896,11 +926,12 @@ _xts2genkey:      if (write(krfd, pblk, TF_FROM_BITS(TFC_KEY_BITS)) == -1) xerror(NO,
                case TFC_CTR_SHOW:
                        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_RAW: xwrite(2, ctr, ctrsz); break;
                                case TFC_OUTFMT_HEX: mehexdump(ctr, ctrsz, ctrsz, YES); break;
                        }
                        break;
                case TFC_CTR_RAND: tfc_getrandom(ctr, ctrsz); break;
+               case TFC_CTR_ZERO: memset(ctr, 0, ctrsz); break;
        }
 
 _ctrskip2:
@@ -926,7 +957,7 @@ _plain:
 
        if (oseek) {
                if (lseek(dfd, oseek, SEEK_SET) == -1)
-                       xerror(YES, NO, NO, "%s: seek failed", dstfname);
+                       xerror(ignore_seek_errors, NO, NO, "%s: seek failed", dstfname);
        }
 
        for (x = 1; x < NSIG; x++) signal(x, SIG_IGN);
@@ -960,7 +991,7 @@ _plain:
                pblk = ctr;
                lio = lrem = ctrsz;
                ldone = 0;
-_ctrwagain:    lio = write(dfd, pblk, lrem);
+_ctrwagain:    lio = xwrite(dfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else xerror(NO, NO, NO, "%s", dstfname);
                if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
@@ -973,6 +1004,8 @@ _ctrwagain:        lio = write(dfd, pblk, lrem);
                delta_processed += ldone;
        }
 
+       if (ctr_mode == TFC_MODE_STREAM) tfe_init_iv(&tfe, key, ctr);
+
        errno = 0;
        do_stop = NO;
        while (1) {
@@ -981,7 +1014,7 @@ _ctrwagain:        lio = write(dfd, pblk, lrem);
                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);
+_ragain:       lio = xread(sfd, pblk, lrem);
                if (lio == 0) do_stop = TFC_STOP_BEGAN;
                if (lio != NOSIZE) ldone += lio;
                else {
@@ -1047,7 +1080,7 @@ _ragain:  lio = read(sfd, pblk, lrem);
                pblk = dstblk;
                lrem = ldone;
                ldone = 0;
-_wagain:       lio = write(dfd, pblk, lrem);
+_wagain:       lio = xwrite(dfd, pblk, lrem);
                if (lio != NOSIZE) ldone += lio;
                else xerror(NO, NO, NO, "%s", dstfname);
                if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
@@ -1071,7 +1104,7 @@ _nowrite: total_processed_dst += ldone;
                        ldone = 0;
                        lrem = lblock = TF_FROM_BITS(macbits);
                        if (error_action == TFC_ERRACT_SYNC) rdpos = tfc_fdgetpos(sfd);
-_macragain:            lio = read(sfd, pblk, lrem);
+_macragain:            lio = xread(sfd, pblk, lrem);
                        if (lio != NOSIZE) ldone += lio;
                        else {
                                if (errno != EIO && catch_all_errors != YES)
@@ -1102,7 +1135,7 @@ _macragain:               lio = read(sfd, pblk, lrem);
                        if (!strcmp(do_mac_file, "-")) mfd = 0;
                        else mfd = open(do_mac_file, O_RDONLY | O_LARGEFILE);
                        if (mfd == -1) xerror(YES, NO, NO, "%s", do_mac_file);
-                       lio = ldone = read(mfd, tmpdata, sizeof(tmpdata));
+                       lio = ldone = xread(mfd, tmpdata, sizeof(tmpdata));
                        if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file);
                        if (!memcmp(tmpdata, TFC_ASCII_TFC_MAC_FOURCC, TFC_ASCII_TFC_MAC_FOURCC_LEN)) {
                                memmove(tmpdata, tmpdata+TFC_ASCII_TFC_MAC_FOURCC_LEN,
@@ -1167,7 +1200,7 @@ _shortmac:        memset(macvrfy, 0, sizeof(macvrfy));
                        pblk = tmpdata;
                        lio = lrem = TF_FROM_BITS(macbits);
                        ldone = 0;
-_macwagain:            lio = write(dfd, pblk, lrem);
+_macwagain:            lio = xwrite(dfd, pblk, lrem);
                        if (lio != NOSIZE) ldone += lio;
                        else xerror(NO, NO, NO, "%s", dstfname);
                        if (do_fsync && fsync(dfd) == -1) xerror(NO, NO, NO, "%s", dstfname);
@@ -1195,9 +1228,9 @@ _macwagain:               lio = write(dfd, pblk, lrem);
                                        tmpdata[lrem] = '\n';
                                        lrem++;
                                }
-                               lio = write(mfd, tmpdata, lrem);
+                               lio = xwrite(mfd, tmpdata, lrem);
                        }
-                       else lio = write(mfd, tmpdata, TF_FROM_BITS(macbits));
+                       else lio = xwrite(mfd, tmpdata, TF_FROM_BITS(macbits));
                        if (lio == NOSIZE) xerror(NO, NO, YES, "%s", do_mac_file);
                        if (do_fsync && fsync(mfd) == -1) xerror(NO, NO, YES, "%s", do_mac_file);
                        xclose(mfd);