Deploy the new <ctype.h> and `foocmp' macros from mLib.
[catacomb] / progs / rspit.c
index 21d94bf..812525f 100644 (file)
@@ -27,6 +27,8 @@
 
 /*----- Header files ------------------------------------------------------*/
 
+#define _FILE_OFFSET_BITS 64
+
 #include "config.h"
 
 #include <assert.h>
@@ -45,6 +47,7 @@
 
 #include <mLib/darray.h>
 #include <mLib/dstr.h>
+#include <mLib/macros.h>
 #include <mLib/mdwopt.h>
 #include <mLib/quis.h>
 #include <mLib/report.h>
@@ -73,6 +76,7 @@
 #include "salsa20.h"
 #include "salsa20-core.h"
 #include "seal.h"
+#include "sha3.h"
 
 #include "des-ofb.h"
 #include "des3-ofb.h"
@@ -232,7 +236,7 @@ enum { SALSAE BOGUS_SALSA };
 #define CHACHA_NAME(r) "chacha" #r
 #define XCHACHA_NAME(r) "xchacha" #r
 
-static struct {
+static const struct {
   size_t noncesz;
   grand *(*gen)(const void *, size_t, const void *);
 } salsatab[] = {
@@ -241,6 +245,27 @@ static struct {
 #undef E
 };
 
+#define SHAKES E(128) E(256)
+
+enum {
+#define E(sz) SHAKE##sz##_INDEX,
+  SHAKES
+#undef E
+  SHAKE__LIMIT
+};
+
+static const struct {
+  const octet *ksz;
+  grand *(*shake)(const void *, size_t, const void *, size_t,
+                 const void *, size_t);
+  grand *(*kmac)(const void *, size_t,
+                const void *, size_t);
+} shaketab[] = {
+#define E(sz) { shake##sz##_keysz, cshake##sz##_rand, kmac##sz##_rand },
+  SHAKES
+#undef E
+};
+
 /*----- Miscellaneous static data -----------------------------------------*/
 
 static FILE *outfp;
@@ -411,7 +436,7 @@ static int opt(void)
       case 'o':
        if (flags & f_file)
          die(EXIT_FAILURE, "already set an output file");
-       if (strcmp(optarg, "-") == 0)
+       if (STRCMP(optarg, ==, "-"))
          outfp = stdout;
        else {
          outfp = fopen(optarg, "w");
@@ -1078,6 +1103,113 @@ static grand *gen_mgf(unsigned i)
   return (r);
 }
 
+/* --- SHAKE generators --- */
+
+static grand *gen_shake(unsigned i)
+{
+  dstr d = DSTR_INIT;
+  const char *func = 0, *perso = 0;
+  grand *r;
+
+  static struct option opts[] = {
+    { "function",      OPTF_ARGREQ,    0,      'F' },
+    { "personalization", OPTF_ARGREQ,  0,      'P' },
+    { "key",           OPTF_ARGREQ,    0,      'k' },
+    { "hex",           OPTF_ARGREQ,    0,      'H' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("F:P:k:H:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'F':
+       func = optarg;
+       break;
+      case 'P':
+       perso = optarg;
+       break;
+      case 'k':
+       DRESET(&d);
+       textkey(&d, optarg, shaketab[i].ksz);
+       break;
+      case 'H':
+       DRESET(&d);
+       hexkey(&d, optarg, shaketab[i].ksz);
+       break;
+      default:
+       return (0);
+    }
+  }
+
+  if (!d.len) randkey(&d, shaketab[i].ksz);
+  r = shaketab[i].shake(func, func ? strlen(func) : 0,
+                       perso, perso ? strlen(perso) : 0,
+                       d.buf, d.len);
+  dstr_destroy(&d);
+  return (r);
+}
+
+/* --- KMAC generators --- */
+
+static grand *gen_kmac(unsigned i)
+{
+  dstr d = DSTR_INIT, m = DSTR_INIT;
+  const char *perso = 0;
+  char *q;
+  grand *r;
+
+  static struct option opts[] = {
+    { "personalization", OPTF_ARGREQ,  0,      'P' },
+    { "key",           OPTF_ARGREQ,    0,      'k' },
+    { "hex",           OPTF_ARGREQ,    0,      'H' },
+    { "message",       OPTF_ARGREQ,    0,      'M' },
+    { "msghex",                OPTF_ARGREQ,    0,      'N' },
+    { 0,               0,              0,      0 }
+  };
+
+  addopts("P:k:H:M:N:", opts);
+
+  for (;;) {
+    int o = opt();
+    if (o < 0)
+      break;
+    switch (o) {
+      case 'P':
+       perso = optarg;
+       break;
+      case 'k':
+       DRESET(&d);
+       textkey(&d, optarg, shaketab[i].ksz);
+       break;
+      case 'H':
+       DRESET(&d);
+       hexkey(&d, optarg, shaketab[i].ksz);
+       break;
+      case 'M':
+       DRESET(&m);
+       DPUTS(&d, optarg);
+       break;
+      case 'N':
+       DRESET(&m);
+       unhex(optarg, &q, &m);
+       if (*q) die(EXIT_FAILURE, "bad hex");
+       break;
+      default:
+       return (0);
+    }
+  }
+
+  if (!d.len) randkey(&d, shaketab[i].ksz);
+  r = shaketab[i].kmac(perso, perso ? strlen(perso) : 0, d.buf, d.len);
+  r->ops->misc(r, GRAND_SEEDBLOCK, (void *)m.buf, m.len);
+  dstr_destroy(&d); dstr_destroy(&m);
+  return (r);
+}
+
 /* --- Fibonacci generator --- */
 
 static grand *gen_fib(unsigned i)
@@ -1189,6 +1321,16 @@ gen generators[] = {
     "[-k KEY-PHRASE] [-H HEX-KEY] [-n NONCE]" },
   SALSAE
 #undef E
+#define E(sz)                                                          \
+  { "shake" #sz,       gen_shake,      SHAKE##sz##_INDEX,              \
+    "[-k KEY-PHRASE] [-H HEX-KEY]" },
+  SHAKES
+#undef E
+#define E(sz)                                                          \
+  { "kmac" #sz,                gen_kmac,       SHAKE##sz##_INDEX,              \
+    "[-k KEY-PHRASE] [-H HEX-KEY] [-m MSG]" },
+  SHAKES
+#undef E
   { "rc4",             gen_rc4,        0,
     "[-k KEY-PHRASE] [-H HEX-KEY]" },
   { "seal",            gen_seal,       0,
@@ -1450,7 +1592,7 @@ int main(int ac, char *av[])
 
     g = 0;
     for (gg = generators; gg->name; gg++) {
-      if (strncmp(arg, gg->name, sz) == 0) {
+      if (STRNCMP(arg, ==, gg->name, sz)) {
        if (gg->name[sz] == 0) {
          g = gg;
          break;