The drbg's lock must be held across calls to RAND_DRBG_generate()
to prevent simultaneous modification of internal state.
This was observed in practice with simultaneous SSL_new() calls attempting
to seed the (separate) per-SSL RAND_DRBG instances from the global
rand_drbg instance; this eventually led to simultaneous calls to
ctr_BCC_update() attempting to increment drbg->bltmp_pos for their
respective partial final block, violating the invariant that bltmp_pos < 16.
The AES operations performed in ctr_BCC_blocks() makes the race window
quite easy to trigger. A value of bltmp_pos greater than 16 induces
catastrophic failure in ctr_BCC_final(), with subtraction overflowing
and leading to an attempt to memset() to zero a very large range,
which eventually reaches an unmapped page and segfaults.
Provide the needed locking in get_entropy_from_parent(), as well as
fixing a similar issue in RAND_priv_bytes(). There is also an
unlocked call to RAND_DRBG_generate() in ssl_randbytes(), but the
requisite serialization is already guaranteed by the requirements on
the application's usage of SSL objects, and no further locking is
needed for correct behavior. In that case, leave a comment noting
the apparent discrepancy and the reason for its safety (at present).
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4328)
The DRBG_RESEED state plays an analogue role to the |reseed_required_flag| in
Appendix B.3.4 of [NIST SP 800-90A Rev. 1]. The latter is a local variable,
the scope of which is limited to the RAND_DRBG_generate() function. Hence there
is no need for a DRBG_RESEED state outside of the generate function. This state
was removed and replaced by a local variable |reseed_required|.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/4328)
Reseeding is handled very differently by the classic RAND_METHOD API
and the new RAND_DRBG api. These differences led to some problems when
the new RAND_DRBG was made the default OpenSSL RNG. In particular,
RAND_add() did not work as expected anymore. These issues are discussed
on the thread '[openssl-dev] Plea for a new public OpenSSL RNG API'
and in Pull Request #4328. This commit fixes the mentioned issues,
introducing the following changes:
- Replace the fixed size RAND_BYTES_BUFFER by a new RAND_POOL API which
facilitates collecting entropy by the get_entropy() callback.
- Don't use RAND_poll()/RAND_add() for collecting entropy from the
get_entropy() callback anymore. Instead, replace RAND_poll() by
RAND_POOL_acquire_entropy().
- Add a new function rand_drbg_restart() which tries to get the DRBG
in an instantiated state by all means, regardless of the current
state (uninstantiated, error, ...) the DRBG is in. If the caller
provides entropy or additional input, it will be used for reseeding.
- Restore the original documented behaviour of RAND_add() and RAND_poll()
(namely to reseed the DRBG immediately) by a new implementation based
on rand_drbg_restart().
- Add automatic error recovery from temporary failures of the entropy
source to RAND_DRBG_generate() using the rand_drbg_restart() function.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/4328)
The one creating the DRBG should instantiate it, it's there that we
know which parameters we should use to instantiate it.
This splits the rand init in two parts to avoid a deadlock
because when the global drbg is created it wands to call
rand_add on the global rand method.
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
GH: #4268
The DRBG callbacks 'get_entropy()' and 'cleanup_entropy()' are designed
in such a way that the randomness buffer does not have to be allocated
by the calling function. It receives the address of a dynamically
allocated buffer from get_entropy() and returns this address to
cleanup_entropy(), where it is freed. If these two calls are properly
paired, the address can be stored in a stack local variable of the
calling function, so there is no need for having a 'randomness' member
(and a 'filled' member) in 'RAND_DRBG'.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
Unlike the NIST DRBG standard, entropy counts are in bits and
buffer lengths are in bytes. This has lead to some confusion and
errors in the past, see my comment on PR 3789.
To clarify the destinction between entropy counts and buffer lengths,
a 'len' suffix has been added to all member names of RAND_DRBG which
represent buffer lengths:
- {min,max}_{entropy,adin,nonce,pers}
+ {min,max}_{entropy,adin,nonce,pers}len
This change makes naming also more consistent, as can be seen in the
diffs, for example:
- else if (adinlen > drbg->max_adin) {
+ else if (adinlen > drbg->max_adinlen) {
Also replaced all 'ent's by 'entropy's, following a suggestion of Paul Dale.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4266)
Use atfork to count child forks, and reseed DRBG when the counts don't
match.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/4101)
Add a new global DRBG for private keys used by RAND_priv_bytes.
Add BN_priv_rand() and BN_priv_rand_range() which use RAND_priv_bytes().
Change callers to use the appropriate BN_priv... function.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/4076)
Give each SSL object it's own DRBG, chained to the parent global
DRBG which is used only as a source of randomness into the per-SSL
DRBG. This is used for all session, ticket, and pre-master secret keys.
It is NOT used for ECDH key generation which use only the global
DRBG. (Doing that without changing the API is tricky, if not impossible.)
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/4050)
If RAND_add wraps around, XOR with existing. Add test to drbgtest that
does the wrap-around.
Re-order seeding and stop after first success.
Add RAND_poll_ex()
Use the DF and therefore lower RANDOMNESS_NEEDED. Also, for child DRBG's,
mix in the address as the personalization bits.
Centralize the entropy callbacks, from drbg_lib to rand_lib.
(Conceptually, entropy is part of the enclosing application.)
Thanks to Dr. Matthias St Pierre for the suggestion.
Various code cleanups:
-Make state an enum; inline RANDerr calls.
-Add RAND_POLL_RETRIES (thanks Pauli for the idea)
-Remove most RAND_seed calls from rest of library
-Rename DRBG_CTX to RAND_DRBG, etc.
-Move some code from drbg_lib to drbg_rand; drbg_lib is now only the
implementation of NIST DRBG.
-Remove blocklength
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/4019)
Ported from the last FIPS release, with DUAL_EC and SHA1 and the
self-tests removed. Since only AES-CTR is supported, other code
simplifications were done. Removed the "entropy blocklen" concept.
Moved internal functions to new include/internal/rand.h.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/3789)