From: Rich Salz Date: Thu, 3 Aug 2017 14:24:03 +0000 (-0400) Subject: Add a DRBG to each SSL object X-Git-Tag: OpenSSL_1_1_1-pre1~900 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ae3947de09522206d61c0206a733517b10a910f8;p=oweals%2Fopenssl.git 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 (Merged from https://github.com/openssl/openssl/pull/4050) --- diff --git a/apps/s_server.c b/apps/s_server.c index 961c738a15..2ff58b67f9 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -67,7 +67,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context); static void close_accept_socket(void); static int init_ssl_connection(SSL *s); 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); static void init_session_cache_ctx(SSL_CTX *sctx); 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 -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 count = 0; diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index e3d97d38d9..a24ec8e2e4 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -78,6 +78,9 @@ RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent) goto err; 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, drbg_release_entropy, NULL, NULL) @@ -98,6 +101,11 @@ err: return NULL; } +RAND_DRBG *RAND_DRBG_get0_global(void) +{ + return &rand_drbg; +} + /* * Uninstantiate |drbg| and free all memory. */ diff --git a/include/internal/rand.h b/include/internal/rand.h index 2f38095231..4e30e38aa1 100644 --- a/include/internal/rand.h +++ b/include/internal/rand.h @@ -32,6 +32,7 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, int prediction_resistance, const unsigned char *adin, size_t adinlen); int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, int interval); +RAND_DRBG *RAND_DRBG_get0_global(void); /* * EXDATA diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 245f5eb172..a2d13bf3d7 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -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 * 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); # define SSL_SESS_CACHE_OFF 0x0000 diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index afb03fde5b..ae485046a4 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -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); 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); return -1; } diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index a2959a3896..e36eb93ca7 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -4213,11 +4213,11 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, size_t len, if (send_time) { unsigned long Time = (unsigned long)time(NULL); unsigned char *p = result; + l2n(Time, p); - /* TODO(size_t): Convert this */ - ret = RAND_bytes(p, (int)(len - 4)); + ret = ssl_randbytes(s, p, len - 4); } else { - ret = RAND_bytes(result, (int)len); + ret = ssl_randbytes(s, result, len); } #ifndef OPENSSL_NO_TLS13DOWNGRADE if (ret) { diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 048669c451..3abb27140b 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -21,6 +21,7 @@ #include #include #include "internal/cryptlib.h" +#include "internal/rand.h" const char SSL_version_str[] = OPENSSL_VERSION_TEXT; @@ -619,10 +620,20 @@ SSL *SSL_new(SSL_CTX *ctx) goto err; s->lock = CRYPTO_THREAD_lock_new(); - if (s->lock == NULL) { - SSLerr(SSL_F_SSL_NEW, ERR_R_MALLOC_FAILURE); - OPENSSL_free(s); - return NULL; + if (s->lock == NULL) + goto err; + + /* + * 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); @@ -1130,6 +1141,7 @@ void SSL_free(SSL *s) sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); #endif + RAND_DRBG_free(s->drbg); CRYPTO_THREAD_lock_free(s->lock); OPENSSL_free(s); @@ -5081,3 +5093,10 @@ uint32_t SSL_get_max_early_data(const SSL *s) { 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); +} diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index ce678a66db..c78c28fe45 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1322,6 +1322,7 @@ struct ssl_st { size_t block_padding; 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, 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_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other); diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index 805a3d75f4..8cd4355cc6 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c @@ -277,12 +277,12 @@ unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s) */ #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 retry = 0; do - if (RAND_bytes(id, *id_len) <= 0) + if (ssl_randbytes(ssl, id, *id_len) <= 0) return 0; while (SSL_has_matching_session_id(ssl, id, *id_len) && (++retry < MAX_SESS_ID_ATTEMPTS)) ; diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 5f6c6b0382..5f2855bcf4 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2816,7 +2816,7 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al) pms[0] = s->client_version >> 8; pms[1] = s->client_version & 0xff; /* 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; } @@ -3006,7 +3006,7 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt, int *al) /* Generate session key * TODO(size_t): Convert this function */ - || RAND_bytes(pms, (int)pmslen) <= 0) { + || ssl_randbytes(s, pms, (int)pmslen) <= 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR); goto err; diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 9d3c387dcd..fad339adb2 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -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 */ - 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; /* @@ -3378,7 +3378,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) } age_add_u; 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; 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(); iv_len = EVP_CIPHER_iv_length(cipher); - if (RAND_bytes(iv, iv_len) <= 0) + if (ssl_randbytes(s, iv, iv_len) <= 0) goto err; if (!EVP_EncryptInit_ex(ctx, cipher, NULL, tctx->ext.tick_aes_key, iv)) diff --git a/ssl/tls_srp.c b/ssl/tls_srp.c index bfdbdf5874..368cacee3d 100644 --- a/ssl/tls_srp.c +++ b/ssl/tls_srp.c @@ -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)) return SSL3_AL_FATAL; - if (RAND_bytes(b, sizeof(b)) <= 0) + if (ssl_randbytes(s, b, sizeof(b)) <= 0) return SSL3_AL_FATAL; s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL); OPENSSL_cleanse(b, sizeof(b)); @@ -343,7 +343,7 @@ int SRP_Calc_A_param(SSL *s) { 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; s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a); OPENSSL_cleanse(rnd, sizeof(rnd)); diff --git a/util/libcrypto.num b/util/libcrypto.num index 023b64908d..c9fa2c48d5 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -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_get_count 4317 1_1_1 EXIST::FUNCTION: RAND_poll_ex 4318 1_1_1 EXIST::FUNCTION: +RAND_DRBG_get0_global 4319 1_1_1 EXIST::FUNCTION: