Add a DRBG to each SSL object

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)
This commit is contained in:
Rich Salz 2017-08-03 10:24:03 -04:00
parent 75e2c87765
commit ae3947de09
13 changed files with 51 additions and 20 deletions

View file

@ -67,7 +67,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context);
static void close_accept_socket(void); static void close_accept_socket(void);
static int init_ssl_connection(SSL *s); static int init_ssl_connection(SSL *s);
static void print_stats(BIO *bp, SSL_CTX *ctx); static void print_stats(BIO *bp, SSL_CTX *ctx);
static int generate_session_id(const SSL *ssl, unsigned char *id, static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len); unsigned int *id_len);
static void init_session_cache_ctx(SSL_CTX *sctx); static void init_session_cache_ctx(SSL_CTX *sctx);
static void free_sessions(void); static void free_sessions(void);
@ -3412,7 +3412,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
} }
#define MAX_SESSION_ID_ATTEMPTS 10 #define MAX_SESSION_ID_ATTEMPTS 10
static int generate_session_id(const SSL *ssl, unsigned char *id, static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len) unsigned int *id_len)
{ {
unsigned int count = 0; unsigned int count = 0;

View file

@ -78,6 +78,9 @@ RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
goto err; goto err;
if (parent != NULL) { if (parent != NULL) {
if (parent->state == DRBG_UNINITIALISED
&& RAND_DRBG_instantiate(parent, NULL, 0) == 0)
goto err;
if (!RAND_DRBG_set_callbacks(drbg, drbg_entropy_from_parent, if (!RAND_DRBG_set_callbacks(drbg, drbg_entropy_from_parent,
drbg_release_entropy, drbg_release_entropy,
NULL, NULL) NULL, NULL)
@ -98,6 +101,11 @@ err:
return NULL; return NULL;
} }
RAND_DRBG *RAND_DRBG_get0_global(void)
{
return &rand_drbg;
}
/* /*
* Uninstantiate |drbg| and free all memory. * Uninstantiate |drbg| and free all memory.
*/ */

View file

@ -32,6 +32,7 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
int prediction_resistance, int prediction_resistance,
const unsigned char *adin, size_t adinlen); const unsigned char *adin, size_t adinlen);
int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, int interval); int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, int interval);
RAND_DRBG *RAND_DRBG_get0_global(void);
/* /*
* EXDATA * EXDATA

View file

@ -622,7 +622,7 @@ __owur int SRP_Calc_A_param(SSL *s);
* bytes. The callback can alter this length to be less if desired. It is * bytes. The callback can alter this length to be less if desired. It is
* also an error for the callback to set the size to zero. * also an error for the callback to set the size to zero.
*/ */
typedef int (*GEN_SESSION_CB) (const SSL *ssl, unsigned char *id, typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id,
unsigned int *id_len); unsigned int *id_len);
# define SSL_SESS_CACHE_OFF 0x0000 # define SSL_SESS_CACHE_OFF 0x0000

View file

@ -892,7 +892,7 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
*/ */
SSLerr(SSL_F_TLS1_ENC, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS1_ENC, ERR_R_INTERNAL_ERROR);
return -1; return -1;
} else if (RAND_bytes(recs[ctr].input, ivlen) <= 0) { } else if (ssl_randbytes(s, recs[ctr].input, ivlen) <= 0) {
SSLerr(SSL_F_TLS1_ENC, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS1_ENC, ERR_R_INTERNAL_ERROR);
return -1; return -1;
} }

View file

@ -4213,11 +4213,11 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, size_t len,
if (send_time) { if (send_time) {
unsigned long Time = (unsigned long)time(NULL); unsigned long Time = (unsigned long)time(NULL);
unsigned char *p = result; unsigned char *p = result;
l2n(Time, p); l2n(Time, p);
/* TODO(size_t): Convert this */ ret = ssl_randbytes(s, p, len - 4);
ret = RAND_bytes(p, (int)(len - 4));
} else { } else {
ret = RAND_bytes(result, (int)len); ret = ssl_randbytes(s, result, len);
} }
#ifndef OPENSSL_NO_TLS13DOWNGRADE #ifndef OPENSSL_NO_TLS13DOWNGRADE
if (ret) { if (ret) {

View file

@ -21,6 +21,7 @@
#include <openssl/async.h> #include <openssl/async.h>
#include <openssl/ct.h> #include <openssl/ct.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include "internal/rand.h"
const char SSL_version_str[] = OPENSSL_VERSION_TEXT; const char SSL_version_str[] = OPENSSL_VERSION_TEXT;
@ -619,10 +620,20 @@ SSL *SSL_new(SSL_CTX *ctx)
goto err; goto err;
s->lock = CRYPTO_THREAD_lock_new(); s->lock = CRYPTO_THREAD_lock_new();
if (s->lock == NULL) { if (s->lock == NULL)
SSLerr(SSL_F_SSL_NEW, ERR_R_MALLOC_FAILURE); goto err;
OPENSSL_free(s);
return NULL; /*
* If not using the standard RAND (say for fuzzing), then don't use a
* chained DRBG.
*/
if (RAND_get_rand_method() == RAND_OpenSSL()) {
s->drbg = RAND_DRBG_new(NID_aes_128_ctr, RAND_DRBG_FLAG_CTR_USE_DF,
RAND_DRBG_get0_global());
if (s->drbg == NULL) {
CRYPTO_THREAD_lock_free(s->lock);
goto err;
}
} }
RECORD_LAYER_init(&s->rlayer, s); RECORD_LAYER_init(&s->rlayer, s);
@ -1130,6 +1141,7 @@ void SSL_free(SSL *s)
sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
#endif #endif
RAND_DRBG_free(s->drbg);
CRYPTO_THREAD_lock_free(s->lock); CRYPTO_THREAD_lock_free(s->lock);
OPENSSL_free(s); OPENSSL_free(s);
@ -5081,3 +5093,10 @@ uint32_t SSL_get_max_early_data(const SSL *s)
{ {
return s->max_early_data; return s->max_early_data;
} }
int ssl_randbytes(SSL *s, unsigned char *rnd, size_t size)
{
if (s->drbg != NULL)
return RAND_DRBG_generate(s->drbg, rnd, size, 0, NULL, 0);
return RAND_bytes(rnd, (int)size);
}

View file

@ -1322,6 +1322,7 @@ struct ssl_st {
size_t block_padding; size_t block_padding;
CRYPTO_RWLOCK *lock; CRYPTO_RWLOCK *lock;
RAND_DRBG *drbg;
}; };
/* /*
@ -2122,6 +2123,7 @@ __owur int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags);
__owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, __owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain,
int ref); int ref);
__owur int ssl_randbytes(SSL *s, unsigned char *buf, size_t num);
__owur int ssl_security(const SSL *s, int op, int bits, int nid, void *other); __owur int ssl_security(const SSL *s, int op, int bits, int nid, void *other);
__owur int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, __owur int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid,
void *other); void *other);

View file

@ -277,12 +277,12 @@ unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s)
*/ */
#define MAX_SESS_ID_ATTEMPTS 10 #define MAX_SESS_ID_ATTEMPTS 10
static int def_generate_session_id(const SSL *ssl, unsigned char *id, static int def_generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len) unsigned int *id_len)
{ {
unsigned int retry = 0; unsigned int retry = 0;
do do
if (RAND_bytes(id, *id_len) <= 0) if (ssl_randbytes(ssl, id, *id_len) <= 0)
return 0; return 0;
while (SSL_has_matching_session_id(ssl, id, *id_len) && while (SSL_has_matching_session_id(ssl, id, *id_len) &&
(++retry < MAX_SESS_ID_ATTEMPTS)) ; (++retry < MAX_SESS_ID_ATTEMPTS)) ;

View file

@ -2816,7 +2816,7 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al)
pms[0] = s->client_version >> 8; pms[0] = s->client_version >> 8;
pms[1] = s->client_version & 0xff; pms[1] = s->client_version & 0xff;
/* TODO(size_t): Convert this function */ /* TODO(size_t): Convert this function */
if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) { if (ssl_randbytes(s, pms + 2, (int)(pmslen - 2)) <= 0) {
goto err; goto err;
} }
@ -3006,7 +3006,7 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al)
/* Generate session key /* Generate session key
* TODO(size_t): Convert this function * TODO(size_t): Convert this function
*/ */
|| RAND_bytes(pms, (int)pmslen) <= 0) { || ssl_randbytes(s, pms, (int)pmslen) <= 0) {
*al = SSL_AD_INTERNAL_ERROR; *al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
goto err; goto err;

View file

@ -2671,7 +2671,7 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
* fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
*/ */
if (RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0) if (ssl_randbytes(s, rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0)
goto err; goto err;
/* /*
@ -3378,7 +3378,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
} age_add_u; } age_add_u;
if (SSL_IS_TLS13(s)) { if (SSL_IS_TLS13(s)) {
if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) if (ssl_randbytes(s, age_add_u.age_add_c, sizeof(age_add_u)) <= 0)
goto err; goto err;
s->session->ext.tick_age_add = age_add_u.age_add; s->session->ext.tick_age_add = age_add_u.age_add;
/* /*
@ -3487,7 +3487,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
const EVP_CIPHER *cipher = EVP_aes_256_cbc(); const EVP_CIPHER *cipher = EVP_aes_256_cbc();
iv_len = EVP_CIPHER_iv_length(cipher); iv_len = EVP_CIPHER_iv_length(cipher);
if (RAND_bytes(iv, iv_len) <= 0) if (ssl_randbytes(s, iv, iv_len) <= 0)
goto err; goto err;
if (!EVP_EncryptInit_ex(ctx, cipher, NULL, if (!EVP_EncryptInit_ex(ctx, cipher, NULL,
tctx->ext.tick_aes_key, iv)) tctx->ext.tick_aes_key, iv))

View file

@ -153,7 +153,7 @@ int SSL_srp_server_param_with_username(SSL *s, int *ad)
(s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL)) (s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
return SSL3_AL_FATAL; return SSL3_AL_FATAL;
if (RAND_bytes(b, sizeof(b)) <= 0) if (ssl_randbytes(s, b, sizeof(b)) <= 0)
return SSL3_AL_FATAL; return SSL3_AL_FATAL;
s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL); s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
OPENSSL_cleanse(b, sizeof(b)); OPENSSL_cleanse(b, sizeof(b));
@ -343,7 +343,7 @@ int SRP_Calc_A_param(SSL *s)
{ {
unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH]; unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
if (RAND_bytes(rnd, sizeof(rnd)) <= 0) if (ssl_randbytes(s, rnd, sizeof(rnd)) <= 0)
return 0; return 0;
s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a); s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
OPENSSL_cleanse(rnd, sizeof(rnd)); OPENSSL_cleanse(rnd, sizeof(rnd));

View file

@ -4372,3 +4372,4 @@ CRYPTO_secure_clear_free 4315 1_1_0g EXIST::FUNCTION:
EVP_PKEY_meth_get0 4316 1_1_1 EXIST::FUNCTION: EVP_PKEY_meth_get0 4316 1_1_1 EXIST::FUNCTION:
EVP_PKEY_meth_get_count 4317 1_1_1 EXIST::FUNCTION: EVP_PKEY_meth_get_count 4317 1_1_1 EXIST::FUNCTION:
RAND_poll_ex 4318 1_1_1 EXIST::FUNCTION: RAND_poll_ex 4318 1_1_1 EXIST::FUNCTION:
RAND_DRBG_get0_global 4319 1_1_1 EXIST::FUNCTION: