diff options
author | Yann Ylavic <ylavic@apache.org> | 2018-06-27 22:17:42 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2018-06-27 22:17:42 +0000 |
commit | 4851f1e00de6ad39ec09c9e8c7403d32a47ba032 (patch) | |
tree | 3d0907483faff8f2ffb7e713b2bd64186f3c0b13 /threadproc | |
parent | 8d59b8cdfa16eeab2bce884bb9b1f7cec5acceac (diff) | |
download | apr-4851f1e00de6ad39ec09c9e8c7403d32a47ba032.tar.gz |
apr_crypto: follow up to r1833359: improve CPRNGs fork()ing.
Rework apr_crypto_prng_after_fork() which now handles rekeying of all the
CPRNGs created within apr_crypto, by maintaining them in a global APR_RING,
with the notable exception of per-thread ones (never forked).
For each maintained CPRNG, apr_crypto_prng_after_fork() will now first rekey
both the parent and child processes (determined by the 'in_child' argument
provided by the caller), and for the parent only rekey a second time so that
the initial states finally differ for both processes. Once these new keys are
committed to their respective CPRNGs, thanks to and in continuity with the
forward secrecy construct of apr_crypto_prng, there will be no in memory key
material or stream that one process can inherit or infer from the other.
The user can also rekey a CPRNG explicitely by calling the new function
apr_crypto_prng_rekey(), and this is done by apr_fork() implicitely before
forking any child, thus for the parent process. This safe guard ensures both
the clearing of the pooled random bytes (buffered keystream) and the renewal
of key material (cheap and preventive against _atfork() handlers or alike).
Rekeying is done by using each CPRNG's keystream directly, there isn't anymore
the use of a PID (or SHA256 thereof) for children processes nor any extra reads
from the system RNG. All the apr_crypto_prng API is now self contained and can
work entirely with a single stream cipher as primitive (Chacha20 or AES256-CTR,
in that order of availability) and the initial entropy of 32 bytes gathered
from the system. IOW, there is only one call issued to the system RNG for the
global CPRNG's initial key, and if more CPRNGs are created their own initial
key is produced by the global CPRNG.
The KAT arrays in the tests suite needed adjustment too because the initial
seed (if provided, like the zeros-input for the KAT) is no more used directly
as the first key. Instead the first 32 bytes of the keystream generated from
the seed are, and the seed (like any just used key) is then cleared immediatly
from internal memory.
Finally some private APR_CRYPTO_PRNG_* macros (in .c file only) are renamed to
CPRNG_* to shorten colomns and avoid multilines in several cases.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1834551 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'threadproc')
-rw-r--r-- | threadproc/unix/proc.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/threadproc/unix/proc.c b/threadproc/unix/proc.c index f7d02d204..950405c09 100644 --- a/threadproc/unix/proc.c +++ b/threadproc/unix/proc.c @@ -223,22 +223,35 @@ APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) memset(proc, 0, sizeof(apr_proc_t)); + /* Rekey PRNG(s) to clear buffer(s) and make sure that the + * state(s) change between fork()s in any case. + */ +#if APU_HAVE_CRYPTO_PRNG + apr_crypto_prng_rekey(NULL); +#endif + if ((pid = fork()) < 0) { return errno; } else if (pid == 0) { proc->pid = getpid(); - apr_random_after_fork(proc); + /* Do the work needed for children PRNG(s). */ #if APU_HAVE_CRYPTO_PRNG - apr_crypto_prng_after_fork(proc); + apr_crypto_prng_after_fork(NULL, 1); #endif + apr_random_after_fork(proc); return APR_INCHILD; } proc->pid = pid; + /* Do the work needed for parent PRNG(s). */ +#if APU_HAVE_CRYPTO_PRNG + apr_crypto_prng_after_fork(NULL, 0); +#endif + return APR_INPARENT; } |