#include "bbs.h"
#include "mprand.h"
+#include "chacha.h"
#include "rc4.h"
+#include "salsa20.h"
+#include "salsa20-core.h"
#include "seal.h"
+#include "sha3.h"
#include "des-ofb.h"
#include "des3-ofb.h"
#undef E
};
+#define SALSAE \
+ E(salsa20, 20,, SALSA20) \
+ E(salsa20, 12,, SALSA20) \
+ E(salsa20, 8,, SALSA20) \
+ E(xsalsa20, 20, X, SALSA20) \
+ E(xsalsa20, 12, X, SALSA20) \
+ E(xsalsa20, 8, X, SALSA20) \
+ E(chacha, 20,, CHACHA) \
+ E(chacha, 12,, CHACHA) \
+ E(chacha, 8,, CHACHA) \
+ E(xchacha, 20, X, CHACHA) \
+ E(xchacha, 12, X, CHACHA) \
+ E(xchacha, 8, X, CHACHA)
+
+#define E(pre, r, x, BASE) pre##_##r##_INDEX,
+enum { SALSAE BOGUS_SALSA };
+#undef E
+
+#define SALSA20_GEN(pre, r) SALSA20_DECOR(pre, r, _rand)
+#define CHACHA_GEN(pre, r) pre##r##_rand
+
+#define SALSA20_NAME(r) SALSA20_NAME_##r
+#define XSALSA20_NAME(r) "x" SALSA20_NAME_##r
+#define CHACHA_NAME(r) "chacha" #r
+#define XCHACHA_NAME(r) "xchacha" #r
+
+static const struct {
+ size_t noncesz;
+ grand *(*gen)(const void *, size_t, const void *);
+} salsatab[] = {
+#define E(pre, r, x, BASE) { x##BASE##_NONCESZ, BASE##_GEN(pre, r) },
+ SALSAE
+#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;
return (r);
}
+/* --- Salsa20, XSalsa20, ChaCha, and XChaCha --- */
+
+static grand *gen_salsae(unsigned i)
+{
+ grand *r;
+ char *p;
+ dstr d = DSTR_INIT;
+ dstr n = DSTR_INIT;
+ kludge64 pos = { 0 };
+ octet posbuf[8];
+ mp *x;
+
+ static struct option opts[] = {
+ { "key", OPTF_ARGREQ, 0, 'k' },
+ { "hex", OPTF_ARGREQ, 0, 'H' },
+ { "nonce", OPTF_ARGREQ, 0, 'n' },
+ { "seek", OPTF_ARGREQ, 0, 's' },
+ { 0, 0, 0, 0 }
+ };
+
+ addopts("k:H:n:s:", opts);
+
+ for (;;) {
+ int o = opt();
+ if (o < 0)
+ break;
+ switch (o) {
+ case 'k':
+ DRESET(&d);
+ textkey(&d, optarg, salsa20_keysz);
+ break;
+ case 'H':
+ DRESET(&d);
+ hexkey(&d, optarg, salsa20_keysz);
+ break;
+ case 'n':
+ DRESET(&n);
+ unhex(optarg, &p, &n);
+ if (*p)
+ die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
+ if (n.len != salsatab[i].noncesz) {
+ die(EXIT_FAILURE, "bad nonce length %lu (must be %lu)",
+ (unsigned long)n.len, (unsigned long)salsatab[i].noncesz);
+ }
+ break;
+ case 's':
+ x = mp_readstring(MP_NEW, optarg, &p, 0);
+ if (*p || MP_NEGP(x) || mp_bits(x) > 64)
+ die(EXIT_FAILURE, "bad position `%s'", optarg);
+ mp_storeb(x, posbuf, sizeof(posbuf));
+ mp_drop(x);
+ LOAD64_(pos, posbuf);
+ break;
+ default:
+ return (0);
+ }
+ }
+
+ if (!d.len)
+ randkey(&d, salsa20_keysz);
+ r = salsatab[i].gen(d.buf, d.len, n.len ? n.buf : 0);
+ r->ops->misc(r, SALSA20_SEEKU64, pos);
+
+ dstr_destroy(&d);
+ dstr_destroy(&n);
+
+ return (r);
+}
+
/* --- Output feedback generators --- */
static grand *gen_ofb(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)
"[-k KEY-PHRASE] [-H HEX-KEY] [-i INDEX]" },
HASHES
#undef E
+#define E(pre, r, x, BASE) \
+ { x##BASE##_NAME(r), gen_salsae, pre##_##r##_INDEX, \
+ "[-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,