X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/fe9de6c9fbf52fa3a0eb0929fd18d615741f1d49..fa54fe1eda6977fc8aef0c154f8483e351e20bdd:/catcrypt.c diff --git a/catcrypt.c b/catcrypt.c index c57fe70..08fbb53 100644 --- a/catcrypt.c +++ b/catcrypt.c @@ -225,16 +225,16 @@ static int encrypt(int argc, char *argv[]) dstr_reset(&d); key_fulltag(k, &d); - e = initenc(eo, ofp, "CATCRYPT ENCRYPTED MESSAGE", 1); + e = initenc(eo, ofp, "CATCRYPT ENCRYPTED MESSAGE"); km = getkem(k, "cckem", 0); if ((err = km->ops->check(km)) != 0) - moan("key `%s' fails check: %s", d.buf, err); + moan("key %s fails check: %s", d.buf, err); if (sk) { dstr_reset(&d); key_fulltag(sk, &d); s = getsig(sk, "ccsig", 1); if ((err = s->ops->check(s)) != 0) - moan("key `%s' fails check: %s", d.buf, err); + moan("key %s fails check: %s", d.buf, err); } /* --- Build the header chunk --- */ @@ -327,10 +327,11 @@ static int encrypt(int argc, char *argv[]) static int decrypt(int argc, char *argv[]) { const char *of = 0; - FILE *ofp = 0; + FILE *ofp = 0, *rfp = 0; FILE *fp = 0; const char *ef = "binary"; int i; + size_t n; dstr d = DSTR_INIT; buf b; key_file kf; @@ -352,11 +353,13 @@ static int decrypt(int argc, char *argv[]) enc *e; #define f_bogus 1u +#define f_buffer 2u for (;;) { static const struct option opt[] = { { "armour", 0, 0, 'a' }, { "armor", 0, 0, 'a' }, + { "buffer", 0, 0, 'b' }, { "verbose", 0, 0, 'v' }, { "quiet", 0, 0, 'q' }, { "format", OPTF_ARGREQ, 0, 'f' }, @@ -367,6 +370,7 @@ static int decrypt(int argc, char *argv[]) if (i < 0) break; switch (i) { case 'a': ef = "pem"; break; + case 'b': f |= f_buffer; break; case 'v': verb++; break; case 'q': if (verb) verb--; break; case 'f': ef = optarg; break; @@ -394,7 +398,7 @@ static int decrypt(int argc, char *argv[]) if (key_open(&kf, keyring, KOPEN_READ, keyreport, 0)) die(EXIT_FAILURE, "can't open keyring `%s'", keyring); - e = initenc(eo, fp, "CATCRYPT ENCRYPTED MESSAGE", 0); + e = initdec(eo, fp, checkbdry, "CATCRYPT ENCRYPTED MESSAGE"); /* --- Read the header chunk --- */ @@ -454,20 +458,25 @@ static int decrypt(int argc, char *argv[]) if (verb) { dstr_reset(&d); key_fulltag(sk, &d); - printf("INFO good signature from %s\n", d.buf); + printf("INFO good-signature %s\n", d.buf); } } else if (verb) - printf("INFO no signature packet\n"); + printf("INFO no-signature\n"); /* --- Now decrypt the main body --- */ if (!of || strcmp(of, "-") == 0) { ofp = stdout; - if (verb) printf("DATA\n"); - } else if ((ofp = fopen(of, "wb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); + f |= f_buffer; } + if (!(f & f_buffer)) { + if ((ofp = fopen(of, "wb")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + ofp, strerror(errno)); + } + rfp = ofp; + } else if ((rfp = tmpfile()) == 0) + die(EXIT_FAILURE, "couldn't create temporary file: %s", strerror(errno)); seq = 0; dstr_ensure(&d, GC_CLASS(c)->blksz); @@ -483,32 +492,48 @@ static int decrypt(int argc, char *argv[]) seq++; chunk_read(e, &d, &b); if ((tag = buf_get(&b, GM_CLASS(m)->hashsz)) == 0) { - if (verb) printf("%sFAIL bad ciphertext chunk: no tag\n", - ofp == stdout ? "\n" : ""); + if (verb) printf("FAIL bad ciphertext chunk: no tag\n"); exit(EXIT_FAILURE); } GH_HASH(h, BCUR(&b), BLEFT(&b)); if (memcmp(tag, GH_DONE(h, 0), GM_CLASS(m)->hashsz) != 0) { if (verb) - printf("%sFAIL bad ciphertext chunk: authentication failure\n", - ofp == stdout ? "\n" : ""); + printf("FAIL bad ciphertext chunk: authentication failure\n"); exit(EXIT_FAILURE); } if (!BLEFT(&b)) break; GC_DECRYPT(c, BCUR(&b), BCUR(&b), BLEFT(&b)); - if (fwrite(BCUR(&b), 1, BLEFT(&b), ofp) != BLEFT(&b)) { - if (verb) printf("%sFAIL error writing output: %s\n", - ofp == stdout ? "\n" : "", strerror(errno)); + if (fwrite(BCUR(&b), 1, BLEFT(&b), rfp) != BLEFT(&b)) { + if (verb) printf("FAIL error writing output: %s\n", strerror(errno)); exit(EXIT_FAILURE); } } - if (fflush(ofp) || ferror(ofp)) { - if (verb) printf("%sFAIL error writing output: %s\n", - ofp == stdout ? "\n" : "", strerror(errno)); + if (fflush(rfp) || ferror(rfp)) { + if (verb) printf("FAIL error writing output: %s\n", strerror(errno)); exit(EXIT_FAILURE); } + if (f & f_buffer) { + if (!ofp && (ofp = fopen(of, "wb")) == 0) { + die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", + of, strerror(errno)); + } + rewind(rfp); + dstr_reset(&d); + dstr_ensure(&d, 65536); + if (ofp == stdout) printf("DATA\n"); + for (;;) { + n = fread(d.buf, 1, d.sz, rfp); + if (!n) break; + if (fwrite(d.buf, 1, n, ofp) < n) + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); + } + if (ferror(rfp) || fclose(rfp)) + die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno)); + } + if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp))) + die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); e->ops->decdone(e); if (verb && ofp != stdout) @@ -524,148 +549,7 @@ static int decrypt(int argc, char *argv[]) return (0); #undef f_bogus -} - -/*----- Test code ---------------------------------------------------------*/ - -static int encode(int argc, char *argv[]) -{ - const char *of = 0; - FILE *ofp = 0; - FILE *fp = 0; - const char *ef = "binary"; - const char *bd = "MESSAGE"; - int i; - size_t n; - char buf[4096]; - unsigned f = 0; - const encops *eo; - enc *e; - -#define f_bogus 1u - - for (;;) { - static const struct option opt[] = { - { "format", OPTF_ARGREQ, 0, 'f' }, - { "boundary", OPTF_ARGREQ, 0, 'b' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "f:b:o:", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'f': ef = optarg; break; - case 'b': bd = optarg; break; - case 'o': of = optarg; break; - default: f |= f_bogus; break; - } - } - if (argc - optind > 1 || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: encode [-OPTIONS] [FILE]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - if (optind == argc) - fp = stdin; - else if (strcmp(argv[optind], "-") == 0) { - fp = stdin; - optind++; - } else if ((fp = fopen(argv[optind], "rb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - argv[optind], strerror(errno)); - } else - optind++; - - if (!of || strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, eo->wmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - - e = initenc(eo, ofp, bd, 1); - - do { - n = fread(buf, 1, sizeof(buf), fp); - if (e->ops->write(e, buf, n)) - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - } while (n == sizeof(buf)); - e->ops->encdone(e); - freeenc(e); - return (0); - -#undef f_bogus -} - -static int decode(int argc, char *argv[]) -{ - const char *of = 0; - FILE *ofp = 0; - FILE *fp = 0; - const char *ef = "binary"; - const char *bd = 0; - int i; - char buf[4096]; - unsigned f = 0; - const encops *eo; - enc *e; - -#define f_bogus 1u - - for (;;) { - static const struct option opt[] = { - { "format", OPTF_ARGREQ, 0, 'f' }, - { "boundary", OPTF_ARGREQ, 0, 'b' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "f:b:o:", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'f': ef = optarg; break; - case 'b': bd = optarg; break; - case 'o': of = optarg; break; - default: f |= f_bogus; break; - } - } - if (argc - optind > 1 || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: decode [-OPTIONS] [FILE]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - if (optind == argc) - fp = stdin; - else if (strcmp(argv[optind], "-") == 0) { - fp = stdin; - optind++; - } else if ((fp = fopen(argv[optind], eo->rmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - argv[optind], strerror(errno)); - } else - optind++; - - if (!of || strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, "wb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - - e = initenc(eo, fp, bd, 0); - - do { - if ((i = e->ops->read(e, buf, sizeof(buf))) < 0) - die(EXIT_FAILURE, "error reading input: %s", strerror(errno)); - if (fwrite(buf, 1, i, ofp) < i) - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - } while (i == sizeof(buf)); - e->ops->decdone(e); - freeenc(e); - return (0); - -#undef f_bogus +#undef f_buffer } /*----- Main code ---------------------------------------------------------*/ @@ -698,24 +582,8 @@ static int cmd_help(int, char **); static cmd cmdtab[] = { { "help", cmd_help, "help [COMMAND...]" }, { "show", cmd_show, "show [ITEM...]" }, - { "encode", encode, - "encode [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]", - "\ -Options:\n\ -\n\ --f, --format=FORMAT Encode to FORMAT.\n\ --b, --boundary=LABEL PEM boundary is LABEL.\n\ --o, --output=FILE Write output to FILE.\n\ -" }, - { "decode", decode, - "decode [-f FORMAT] [-b LABEL] [-o OUTPUT] [FILE]", - "\ -Options:\n\ -\n\ --f, --format=FORMAT Decode from FORMAT.\n\ --b, --boundary=LABEL PEM boundary is LABEL.\n\ --o, --output=FILE Write output to FILE.\n\ -" }, + CMD_ENCODE, + CMD_DECODE, { "encrypt", encrypt, "encrypt [-a] [-k TAG] [-s TAG] [-f FORMAT]\n\t\ [-o OUTPUT] [FILE]", "\ @@ -728,15 +596,16 @@ Options:\n\ -o, --output=FILE Write output to FILE.\n\ " }, { "decrypt", decrypt, - "decrypt [-aqv] [-f FORMAT] [-o OUTPUT] [FILE]", "\ + "decrypt [-abqv] [-f FORMAT] [-o OUTPUT] [FILE]", "\ Options:\n\ \n\ -a, --armour Same as `-f pem'.\n\ --v, --verbose Produce more verbose messages.\n\ --q, --quiet Produce fewer messages.\n\ +-b, --buffer Buffer output until we're sure we have it all.\n\ -f, --format=FORMAT Decode as FORMAT.\n\ -o, --output=FILE Write output to FILE.\n\ -" }, +-q, --quiet Produce fewer messages.\n\ +-v, --verbose Produce more verbose messages.\n\ +" }, /* ' emacs is confused */ { 0, 0, 0 } };