Merge branch '2.5.x'
[catacomb] / progs / catcrypt.c
index 5879ecb..c31a3d9 100644 (file)
@@ -51,6 +51,7 @@
 #include "key.h"
 #include "cc.h"
 
+#include "gaead.h"
 #include "ectab.h"
 #include "ptab.h"
 
@@ -137,7 +138,6 @@ static int encrypt(int argc, char *argv[])
   int en;
   size_t n, chsz;
   dstr d = DSTR_INIT;
-  octet *tag, *ct;
   buf b;
   size_t seq;
   char bb[65536];
@@ -146,10 +146,8 @@ static int encrypt(int argc, char *argv[])
   key *k;
   key *sk = 0;
   kem *km;
+  bulk *bc;
   sig *s = 0;
-  gcipher *cx, *c;
-  gmac *m;
-  ghash *h;
   const encops *eo;
   enc *e;
 
@@ -213,7 +211,7 @@ static int encrypt(int argc, char *argv[])
   dstr_reset(&d);
   key_fulltag(k, &d);
   e = initenc(eo, ofp, "CATCRYPT ENCRYPTED MESSAGE");
-  km = getkem(k, "cckem", 0);
+  km = getkem(k, "cckem", 0, &bc);
   if (!(f & f_nocheck) && (err = km->ops->check(km)) != 0)
     moan("key %s fails check: %s", d.buf, err);
   if (sk) {
@@ -238,8 +236,7 @@ static int encrypt(int argc, char *argv[])
   /* --- Build the KEM chunk --- */
 
   dstr_reset(&d);
-  if (setupkem(km, &d, &cx, &c, &m))
-    die(EXIT_FAILURE, "failed to encapsulate key");
+  if (setupkem(km, &d, bc)) die(EXIT_FAILURE, "failed to encapsulate key");
   buf_init(&b, d.buf, d.len);
   BSTEP(&b, d.len);
   if (s) GH_HASHBUF16(s->h, BBASE(&b), BLEN(&b));
@@ -248,7 +245,7 @@ static int encrypt(int argc, char *argv[])
   /* --- Write the signature chunk --- */
 
   if (s) {
-    GC_ENCRYPT(cx, 0, bb, 1024);
+    GC_ENCRYPT(km->cx, 0, bb, 1024);
     GH_HASH(s->h, bb, 1024);
     dstr_reset(&d);
     if ((en = s->ops->doit(s, &d)) != 0)
@@ -267,48 +264,27 @@ static int encrypt(int argc, char *argv[])
     }
   }
 
-  assert(GC_CLASS(c)->blksz <= sizeof(bb));
-  dstr_ensure(&d, sizeof(bb) + GM_CLASS(m)->hashsz);
+  n = bc->ops->overhead(bc);
+  dstr_ensure(&d, sizeof(bb) + n);
   seq = 0;
-  chsz = MASK16 - GM_CLASS(m)->hashsz;
-  for (;;) {
-    h = GM_INIT(m);
-    GH_HASHU32(h, seq);
-    seq++;
-    if (GC_CLASS(c)->blksz) {
-      GC_ENCRYPT(cx, 0, bb, GC_CLASS(c)->blksz);
-      GC_SETIV(c, bb);
-    }
+  chsz = MASK16 - n;
+  do {
     n = fread(bb, 1, chsz, fp);
-    if (!n) break;
     if (f & f_progress) fprogress_update(&ff, n);
     buf_init(&b, d.buf, d.sz);
-    tag = buf_get(&b, GM_CLASS(m)->hashsz);
-    ct = buf_get(&b, n);
-    assert(tag); assert(ct);
-    GC_ENCRYPT(c, bb, ct, n);
-    GH_HASH(h, ct, n);
-    GH_DONE(h, tag);
-    GH_DESTROY(h);
+    if ((err = bc->ops->doit(bc, seq, &b, bb, n)) != 0) {
+      if (f & f_progress) fprogress_done(&ff);
+      die(EXIT_FAILURE, "failed to encrypt packet: %s\n", err);
+    }
+    seq++;
     chunk_write(e, &b);
-  }
-
-  /* --- Final terminator packet --- */
-
-  buf_init(&b, d.buf, d.sz);
-  tag = buf_get(&b, GM_CLASS(m)->hashsz);
-  assert(tag);
-  GH_DONE(h, tag);
-  GH_DESTROY(h);
-  chunk_write(e, &b);
+  } while (n);
 
   /* --- All done --- */
 
   if (f & f_progress) fprogress_done(&ff);
   e->ops->encdone(e);
-  GM_DESTROY(m);
-  GC_DESTROY(c);
-  GC_DESTROY(cx);
+  bc->ops->destroy(bc);
   freeenc(e);
   if (s) freesig(s);
   freekem(km);
@@ -335,6 +311,7 @@ static int decrypt(int argc, char *argv[])
   int i;
   size_t n;
   dstr d = DSTR_INIT;
+  char bb[65536];
   buf b;
   key_file kf;
   size_t seq;
@@ -343,11 +320,7 @@ static int decrypt(int argc, char *argv[])
   key *sk = 0;
   kem *km;
   sig *s = 0;
-  gcipher *cx;
-  gcipher *c;
-  ghash *h;
-  gmac *m;
-  octet *tag;
+  bulk *bc;
   unsigned f = 0;
   const encops *eo;
   const char *err;
@@ -456,14 +429,14 @@ static int decrypt(int argc, char *argv[])
 
   /* --- Find the key --- */
 
-  km = getkem(k, "cckem", 1);
+  km = getkem(k, "cckem", 1, &bc);
 
   /* --- Read the KEM chunk --- */
 
   chunk_read(e, &d, &b);
   if (f & f_progress)
     fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
-  if (setupkem(km, &d, &cx, &c, &m)) {
+  if (setupkem(km, &d, bc)) {
     if (f & f_progress) fprogress_done(&ff);
     if (verb) printf("FAIL failed to decapsulate key\n");
     exit(EXIT_FAILURE);
@@ -475,7 +448,7 @@ static int decrypt(int argc, char *argv[])
   if (sk) {
     dstr_reset(&d);
     dstr_ensure(&d, 1024);
-    GC_ENCRYPT(cx, 0, d.buf, 1024);
+    GC_ENCRYPT(km->cx, 0, d.buf, 1024);
     GH_HASH(s->h, d.buf, 1024);
     chunk_read(e, &d, &b);
     if (f & f_progress)
@@ -516,36 +489,21 @@ static int decrypt(int argc, char *argv[])
   }
 
   seq = 0;
-  dstr_ensure(&d, GC_CLASS(c)->blksz);
+  dstr_ensure(&d, bc->ops->overhead(bc));
   dstr_ensure(&d, 4);
   for (;;) {
-    if (GC_CLASS(c)->blksz) {
-      GC_ENCRYPT(cx, 0, d.buf, GC_CLASS(c)->blksz);
-      GC_SETIV(c, d.buf);
-    }
-    h = GM_INIT(m);
-    GH_HASHU32(h, seq);
-    seq++;
     chunk_read(e, &d, &b);
     if (f & f_progress)
       fprogress_update(&ff, BLEFT(&b)*e->ops->ncook/e->ops->nraw);
-    if ((tag = buf_get(&b, GM_CLASS(m)->hashsz)) == 0) {
+    buf_init(&b, bb, sizeof(bb));
+    if ((err = bc->ops->doit(bc, seq, &b, d.buf, d.len)) != 0) {
       if (f & f_progress) fprogress_done(&ff);
-      if (verb) printf("FAIL bad ciphertext chunk: no tag\n");
+      if (verb) printf("FAIL bad ciphertext chunk: %s\n", err);
       exit(EXIT_FAILURE);
     }
-    GH_HASH(h, BCUR(&b), BLEFT(&b));
-    if (!ct_memeq(tag, GH_DONE(h, 0), GM_CLASS(m)->hashsz)) {
-      if (f & f_progress) fprogress_done(&ff);
-      if (verb)
-       printf("FAIL bad ciphertext chunk: authentication failure\n");
-      exit(EXIT_FAILURE);
-    }
-    GH_DESTROY(h);
-    if (!BLEFT(&b))
-      break;
-    GC_DECRYPT(c, BCUR(&b), BCUR(&b), BLEFT(&b));
-    if (fwrite(BCUR(&b), 1, BLEFT(&b), rfp) != BLEFT(&b)) {
+    seq++;
+    if (!BLEN(&b)) break;
+    if (fwrite(BBASE(&b), 1, BLEN(&b), rfp) != BLEN(&b)) {
       if (f & f_progress) fprogress_done(&ff);
       if (verb) printf("FAIL error writing output: %s\n", strerror(errno));
       exit(EXIT_FAILURE);
@@ -586,10 +544,8 @@ static int decrypt(int argc, char *argv[])
     printf("OK decrypted successfully\n");
   if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
       die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+  bc->ops->destroy(bc);
   freeenc(e);
-  GC_DESTROY(c);
-  GC_DESTROY(cx);
-  GM_DESTROY(m);
   freekem(km);
   if (fp != stdin) fclose(fp);
   key_close(&kf);
@@ -609,12 +565,16 @@ static int decrypt(int argc, char *argv[])
      listtab[i].name, listtab[i].name)                                 \
   LI("Key-encapsulation mechanisms", kem,                              \
      kemtab[i].name, kemtab[i].name)                                   \
+  LI("Bulk crypto transforms", bulk,                                   \
+     bulktab[i].name, bulktab[i].name)                                 \
   LI("Signature schemes", sig,                                         \
      sigtab[i].name, sigtab[i].name)                                   \
   LI("Encodings", enc,                                                 \
      enctab[i].name, enctab[i].name)                                   \
   LI("Symmetric encryption algorithms", cipher,                                \
      gciphertab[i], gciphertab[i]->name)                               \
+  LI("Authenticated encryption schemes", aead,                         \
+     gaeadtab[i], gaeadtab[i]->name)                                   \
   LI("Hash functions", hash,                                           \
      ghashtab[i], ghashtab[i]->name)                                   \
   LI("Message authentication codes", mac,                              \