diff options
author | Dr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> | 2017-08-31 23:16:22 +0200 |
---|---|---|
committer | Ben Kaduk <kaduk@mit.edu> | 2017-10-18 08:39:20 -0500 |
commit | c16de9d8329d41a2433d0f273c080d9d06ad7a87 (patch) | |
tree | 3bdcf5e354efd8991aa1f7d83921655e81db726b /include | |
parent | af1d638730bdfad85a7fa8c3f157b2828eda7c1d (diff) |
Fix reseeding issues of the public RAND_DRBG
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)
Diffstat (limited to 'include')
-rw-r--r-- | include/internal/rand.h | 45 | ||||
-rw-r--r-- | include/openssl/ossl_typ.h | 1 | ||||
-rw-r--r-- | include/openssl/rand.h | 1 | ||||
-rw-r--r-- | include/openssl/randerr.h | 13 |
4 files changed, 59 insertions, 1 deletions
diff --git a/include/internal/rand.h b/include/internal/rand.h index 07f141d6cc..feda9beaa1 100644 --- a/include/internal/rand.h +++ b/include/internal/rand.h @@ -14,6 +14,17 @@ #define RAND_DRBG_FLAG_CTR_USE_DF 0x2 /* + * Default security strength (in the sense of [NIST SP 800-90Ar1]) + * of the default OpenSSL DRBG, and the corresponding NID. + * + * Currently supported values: 128, 192, 256 + * + * TODO(DRBG): would be nice to have the strength configurable + */ +# define RAND_DRBG_STRENGTH 128 +# define RAND_DRBG_NID NID_aes_128_ctr + +/* * Object lifetime functions. */ RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent); @@ -64,4 +75,38 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *dctx, RAND_DRBG_get_nonce_fn get_nonce, RAND_DRBG_cleanup_nonce_fn cleanup_nonce); +/* + * RAND_POOL functions + */ +RAND_POOL *RAND_POOL_new(int entropy_requested, size_t min_len, size_t max_len); +void RAND_POOL_free(RAND_POOL *pool); + +const unsigned char *RAND_POOL_buffer(RAND_POOL *pool); +unsigned char *RAND_POOL_detach(RAND_POOL *pool); + +size_t RAND_POOL_entropy(RAND_POOL *pool); +size_t RAND_POOL_length(RAND_POOL *pool); + +size_t RAND_POOL_entropy_available(RAND_POOL *pool); +size_t RAND_POOL_entropy_needed(RAND_POOL *pool); +size_t RAND_POOL_bytes_needed(RAND_POOL *pool, unsigned int entropy_per_byte); +size_t RAND_POOL_bytes_remaining(RAND_POOL *pool); + +size_t RAND_POOL_add(RAND_POOL *pool, + const unsigned char *buffer, size_t len, size_t entropy); +unsigned char *RAND_POOL_add_begin(RAND_POOL *pool, size_t len); +size_t RAND_POOL_add_end(RAND_POOL *pool, size_t len, size_t entropy); + + +/* + * Add random bytes to the pool to acquire requested amount of entropy + * + * This function is platform specific and tries to acquire the requested + * amount of entropy by polling platform specific entropy sources. + * + * If the function succeeds in acquiring at least |entropy_requested| bits + * of entropy, the total entropy count is returned. If it fails, it returns + * an entropy count of 0. + */ +size_t RAND_POOL_acquire_entropy(RAND_POOL *pool); #endif diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h index b00777694f..f5214ab1e5 100644 --- a/include/openssl/ossl_typ.h +++ b/include/openssl/ossl_typ.h @@ -115,6 +115,7 @@ typedef struct ec_key_method_st EC_KEY_METHOD; typedef struct rand_meth_st RAND_METHOD; typedef struct rand_drbg_st RAND_DRBG; +typedef struct rand_pool_st RAND_POOL; typedef struct ssl_dane_st SSL_DANE; typedef struct x509_st X509; diff --git a/include/openssl/rand.h b/include/openssl/rand.h index 82e3762690..2dec35ea53 100644 --- a/include/openssl/rand.h +++ b/include/openssl/rand.h @@ -64,7 +64,6 @@ int RAND_egd_bytes(const char *path, int bytes); typedef void (*RAND_poll_cb)(void *arg, const void *buf, int num, double randomness); int RAND_poll(void); -int RAND_poll_ex(RAND_poll_cb rand_add, void *arg); # if defined(_WIN32) && (defined(BASETYPES) || defined(_WINDEF_H)) /* application has to include <windows.h> in order to use these */ diff --git a/include/openssl/randerr.h b/include/openssl/randerr.h index 79c652fcdf..b07ea233eb 100644 --- a/include/openssl/randerr.h +++ b/include/openssl/randerr.h @@ -24,14 +24,21 @@ int ERR_load_RAND_strings(void); */ # define RAND_F_DRBG_BYTES 101 # define RAND_F_DRBG_GET_ENTROPY 105 +# define RAND_F_DRBG_SETUP 117 # define RAND_F_GET_ENTROPY 106 # define RAND_F_RAND_BYTES 100 # define RAND_F_RAND_DRBG_GENERATE 107 # define RAND_F_RAND_DRBG_INSTANTIATE 108 # define RAND_F_RAND_DRBG_NEW 109 # define RAND_F_RAND_DRBG_RESEED 110 +# define RAND_F_RAND_DRBG_RESTART 102 # define RAND_F_RAND_DRBG_SET 104 # define RAND_F_RAND_LOAD_FILE 111 +# define RAND_F_RAND_POOL_ADD 103 +# define RAND_F_RAND_POOL_ADD_BEGIN 113 +# define RAND_F_RAND_POOL_ADD_END 114 +# define RAND_F_RAND_POOL_BYTES_NEEDED 115 +# define RAND_F_RAND_POOL_NEW 116 # define RAND_F_RAND_WRITE_FILE 112 /* @@ -39,13 +46,18 @@ int ERR_load_RAND_strings(void); */ # define RAND_R_ADDITIONAL_INPUT_TOO_LONG 102 # define RAND_R_ALREADY_INSTANTIATED 103 +# define RAND_R_ARGUMENT_OUT_OF_RANGE 105 # define RAND_R_CANNOT_OPEN_FILE 121 # define RAND_R_DRBG_NOT_INITIALISED 104 +# define RAND_R_ENTROPY_INPUT_TOO_LONG 106 +# define RAND_R_ENTROPY_OUT_OF_RANGE 124 +# define RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED 127 # define RAND_R_ERROR_INITIALISING_DRBG 107 # define RAND_R_ERROR_INSTANTIATING_DRBG 108 # define RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT 109 # define RAND_R_ERROR_RETRIEVING_ENTROPY 110 # define RAND_R_ERROR_RETRIEVING_NONCE 111 +# define RAND_R_FAILED_TO_CREATE_LOCK 126 # define RAND_R_FUNC_NOT_IMPLEMENTED 101 # define RAND_R_FWRITE_ERROR 123 # define RAND_R_GENERATE_ERROR 112 @@ -55,6 +67,7 @@ int ERR_load_RAND_strings(void); # define RAND_R_NOT_INSTANTIATED 115 # define RAND_R_PERSONALISATION_STRING_TOO_LONG 116 # define RAND_R_PRNG_NOT_SEEDED 100 +# define RAND_R_RANDOM_POOL_OVERFLOW 125 # define RAND_R_REQUEST_TOO_LARGE_FOR_DRBG 117 # define RAND_R_RESEED_ERROR 118 # define RAND_R_SELFTEST_FAILURE 119 |