Add a DRBG to each SSL object
authorRich Salz <rsalz@openssl.org>
Thu, 3 Aug 2017 14:24:03 +0000 (10:24 -0400)
committerRich Salz <rsalz@openssl.org>
Thu, 3 Aug 2017 14:24:03 +0000 (10:24 -0400)
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)

13 files changed:
apps/s_server.c
crypto/rand/drbg_lib.c
include/internal/rand.h
include/openssl/ssl.h
ssl/record/ssl3_record.c
ssl/s3_lib.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/ssl_sess.c
ssl/statem/statem_clnt.c
ssl/statem/statem_srvr.c
ssl/tls_srp.c
util/libcrypto.num

index 961c738a15178a43f9cc98975a3e9ef51809987a..2ff58b67f9c99ebcac984b978e3ddc8e6fcf9276 100644 (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 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;
index e3d97d38d96e3f79988dfd8ca2e7746bcad81319..a24ec8e2e4961de1ff41765e2ddc04094bd6253c 100644 (file)
@@ -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.
  */
index 2f380952314cf6bb070a639399abe4c6673d2d12..4e30e38aa123c343176745095f62948b6fee6875 100644 (file)
@@ -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
index 245f5eb172cfc3ae095bfd7c6a75e623b5994f91..a2d13bf3d74a3e1f64ef182b9884f0ecc3cdd468 100644 (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
  * 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
index afb03fde5be353608d34678450ef53e0f17c83b9..ae485046a44af8c40bd2f2771de5038564cdc9ec 100644 (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);
                         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;
                     }
index a2959a3896da9e8c6ece04632f4fcaf46747ed37..e36eb93ca7834591038413f0c32a6ded491fd4cd 100644 (file)
@@ -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) {
index 048669c45134ef4dd3109a5582edf8ea21ac26bd..3abb27140b08db244d5b6be8f11b0d90006b1b49 100644 (file)
@@ -21,6 +21,7 @@
 #include <openssl/async.h>
 #include <openssl/ct.h>
 #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);
+}
index ce678a66dbb98860eb682d559e05e970815b9d66..c78c28fe45e35219d7b0b3458a76da71ddc20a71 100644 (file)
@@ -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);
index 805a3d75f4579a0d421f0574404ea5d2905311a7..8cd4355cc6382cd2479256fc106adf5cd7ec7ad9 100644 (file)
@@ -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)) ;
index 5f6c6b0382e6d1627ee3bc2bfd4dfe28237afb78..5f2855bcf4b027cebe7567298b759ed34ef364f9 100644 (file)
@@ -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;
index 9d3c387dcd66b8cc1a87b3465809b5330fb4eca4..fad339adb2bd2cf5c410f76deab707f4df0d5c00 100644 (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
      */
 
-    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))
index bfdbdf58744d5cd9236262058ff7e7e5656e6dbf..368cacee3d5c6cbd5d8c7167d47af1c1bd43181e 100644 (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))
         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));
index 023b64908dcd5d04d19c93d386a3da1446d6fc3f..c9fa2c48d57c1ca2c1472b034cd74b5805177f76 100644 (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_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: