X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/bafe8a7b569c884c23e1e21219b49cb1a7fb2480..6a024d24d97cb5d42c0091571735475b849f59f4:/progs/rspit.c diff --git a/progs/rspit.c b/progs/rspit.c index 1fb33a9d..66a05389 100644 --- a/progs/rspit.c +++ b/progs/rspit.c @@ -27,6 +27,8 @@ /*----- Header files ------------------------------------------------------*/ +#define _FILE_OFFSET_BITS 64 + #include "config.h" #include @@ -40,6 +42,7 @@ #ifndef PORTABLE # include +# include #endif #include @@ -67,8 +70,12 @@ #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" @@ -202,6 +209,62 @@ static const struct { #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; @@ -804,6 +867,75 @@ static grand *gen_seal(unsigned i) 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) @@ -970,6 +1102,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) @@ -1076,6 +1315,21 @@ gen generators[] = { "[-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, @@ -1124,6 +1378,22 @@ static int genmaurer(const void *buf, size_t sz, void *p) return (0); } +static double doubletime(void) +{ +#ifdef PORTABLE + static time_t start = (time_t)-1; + time_t now = time(0); + + if (start == (time_t)-1) start = now; + return difftime(now, start); +#else + struct timeval tv; + + gettimeofday(&tv, 0); + return (tv.tv_sec + tv.tv_usec/1000000.0); +#endif +} + static int generate(grand *r, mp *outsz, int (*func)(const void *buf, size_t sz, void *p), void *p) @@ -1133,7 +1403,7 @@ static int generate(grand *r, mp *outsz, unsigned percent = 0; mp *kb = MP_ZERO, *t = MP_NEW; dstr d = DSTR_INIT; - time_t last; + double now, last; static char baton[] = "-\\|/"; char *bp; int rc; @@ -1141,7 +1411,7 @@ static int generate(grand *r, mp *outsz, /* --- Spit out random data --- */ - last = time(0); + last = doubletime(); bp = baton; if (flags & f_progress) { char *errbuf = xmalloc(BUFSIZ); @@ -1184,14 +1454,15 @@ static int generate(grand *r, mp *outsz, /* --- Update the display --- */ if (flags & f_progress) { - time_t now = time(0); unsigned up = 0; + now = doubletime(); + if (percent > 100) up = 1; if (!outsz) { - if (difftime(now, last) > 1.0) { + if (now - last > 0.1) { up = 1; } if (up) @@ -1203,7 +1474,7 @@ static int generate(grand *r, mp *outsz, mp_div(&t, 0, t, outsz); assert(!MP_NEGP(t) && MP_CMP(t, <, MP_UINT_MAX)); pc = mp_touint(t); - if (pc > percent || percent > 100 || difftime(now, last) > 1.0) { + if (pc > percent || percent > 100 || now - last > 0.1) { if (percent > 100) percent = 0; percent &= ~1; @@ -1238,7 +1509,7 @@ static int generate(grand *r, mp *outsz, if (percent > 100) percent = 0; - if (percent < 100) { + if (percent < 100 && up) { putc(*bp++, stderr); putc('\b', stderr); if (!*bp)