This is fiddlier than it really ought to be.
* Make the `i' and `irot' members be `unsigned short' to make space
for a new member. These members have well-constrained ranges, so
this is safe.
* Insert a new `gen' member to keep track of the pool's `generation
number'. Arrange that the global generator's generation number is
initially zero.
* Invent a new system-specific function `rand_generation' which
returns a nonzero `generation number', which changes across forks
and such things.
* Have the output functions `rand_get' and `rand_getgood' check the
generation number and force a `rand_gate' if it changes.
* Arrange for `rand_gate' and `rand_stretch' to feed the generation
number into the hashing, so that generators with different
generations behave computationally independently.
## Cryptographic laundering for true random data generation.
pkginclude_HEADERS += rand.h
librand_la_SOURCES += rand.c
+librand_la_SOURCES += randgen.c
## The SSL v3 pseudorandom function.
pkginclude_HEADERS += sslprf.h
gctx rand_global = {
{ &gops },
- { { 0 }, 0, 0, 0,
+ { { 0 }, 0, 0, 0, 0,
{ 0 }, RAND_SECSZ, 0,
{ "Catacomb global random byte pool" },
&noise_source }
#define RAND_RESOLVE(r) \
do { if ((r) == RAND_GLOBAL) r = &rand_global.p; } while (0)
+#define GENCHECK(r) do { \
+ unsigned gen = rand_generation(); \
+ if (r->gen != gen) { r->gen = gen; rand_gate(r); } \
+} while (0)
+
#define TIMER(r) do { \
if ((r)->s && (r)->s->timer) \
(r)->s->timer(r); \
RAND_RESOLVE(r);
memset(r->pool, 0, sizeof(r->pool));
memset(r->buf, 0, sizeof(r->buf));
+ r->gen = rand_generation();
r->i = 0;
r->irot = 0;
r->ibits = r->obits = 0;
void rand_gate(rand_pool *r)
{
- octet h[HASH_SZ];
+ octet h[HASH_SZ], g[4];
HASH_CTX hc;
CIPHER_CTX cc;
/* --- Hash up all the data in the pool --- */
HASH_INIT(&hc);
+ STORE32(g, r->gen); HASH(&hc, g, sizeof(g));
HASH(&hc, r->pool, RAND_POOLSZ);
HASH(&hc, r->buf, RAND_BUFSZ);
HASH_DONE(&hc, h);
void rand_stretch(rand_pool *r)
{
- octet h[HASH_SZ];
+ octet h[HASH_SZ], g[4];
HASH_CTX hc;
CIPHER_CTX cc;
/* --- Hash up all the data in the buffer --- */
HASH_INIT(&hc);
+ STORE32(g, r->gen); HASH(&hc, g, sizeof(g));
HASH(&hc, r->pool, RAND_POOLSZ);
HASH(&hc, r->buf, RAND_BUFSZ);
HASH_DONE(&hc, h);
octet *o = p;
RAND_RESOLVE(r);
+ GENCHECK(r);
TIMER(r);
if (!sz)
rand_get(r, p, sz);
return;
}
+ GENCHECK(r);
TIMER(r);
while (sz) {
typedef struct rand_pool {
octet pool[RAND_POOLSZ]; /* Actual contents of the pool */
- unsigned i; /* Current index into pool */
- unsigned irot; /* Current rotation applied */
+ unsigned gen; /* Generation number */
+ unsigned short i; /* Current index into pool */
+ unsigned short irot; /* Current rotation applied */
unsigned ibits; /* Number of good bits in pool */
octet buf[RAND_BUFSZ]; /* Random octet output buffer */
unsigned o; /* Current index into buffer */
extern void rand_init(rand_pool */*r*/);
+/* --- @rand_generation@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: A nonzero generation number.
+ *
+ * Use: Returns a generation number for the current process. Each
+ * pool has its own number. If this matches the process number
+ * then all is well. If it doesn't match, then the pool needs
+ * to be cleaned before its next use.
+ */
+
+extern unsigned rand_generation(void);
+
/* --- @rand_noisesrc@ --- *
*
* Arguments: @rand_pool *r@ = pointer to a randomness pool
--- /dev/null
+/* -*-c-*-
+ *
+ * Pool-generation boundary machinery (Unix-specific)
+ *
+ * (c) 2016 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <unistd.h>
+
+#include "rand.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rand_generation@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: A nonzero generation number.
+ *
+ * Use: Returns a generation number for the current process. Each
+ * pool has its own number. If this matches the process number
+ * then all is well. If it doesn't match, then the pool needs
+ * to be cleaned before its next use.
+ */
+
+unsigned rand_generation(void) { return (getpid()); }
+
+/*----- That's all, folks -------------------------------------------------*/