#ifndef PORTABLE
# include <unistd.h>
+# include <sys/time.h>
#endif
#include <mLib/darray.h>
#include "bbs.h"
#include "mprand.h"
+#include "chacha.h"
#include "rc4.h"
+#include "salsa20.h"
+#include "salsa20-core.h"
#include "seal.h"
#include "des-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 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
+};
+
/*----- 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)
"[-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
{ "rc4", gen_rc4, 0,
"[-k KEY-PHRASE] [-H HEX-KEY]" },
{ "seal", gen_seal, 0,
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)
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;
/* --- Spit out random data --- */
- last = time(0);
+ last = doubletime();
bp = baton;
if (flags & f_progress) {
char *errbuf = xmalloc(BUFSIZ);
/* --- 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)
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;
if (percent > 100)
percent = 0;
- if (percent < 100) {
+ if (percent < 100 && up) {
putc(*bp++, stderr);
putc('\b', stderr);
if (!*bp)