Fix: uninstantiation breaks the RAND_DRBG callback mechanism
authorDr. Matthias St. Pierre <matthias.st.pierre@ncp-e.com>
Mon, 20 Jul 2020 21:21:37 +0000 (23:21 +0200)
committerDr. Matthias St. Pierre <matthias.st.pierre@ncp-e.com>
Wed, 22 Jul 2020 23:12:48 +0000 (01:12 +0200)
The RAND_DRBG callbacks are wrappers around the EVP_RAND callbacks.
During uninstantiation, the EVP_RAND callbacks got lost while the
RAND_DRBG callbacks remained, because RAND_DRBG_uninstantiate()
calls RAND_DRBG_set(), which recreates the EVP_RAND object.
This was causing drbgtest failures.

This commit fixes the problem by adding code to RAND_DRBG_set() for
saving and restoring the EVP_RAND callbacks.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11195)

crypto/rand/drbg_lib.c

index 4b5d832df21a867c8750e5084e67c1e33490dc27..d2566920cd55ad2c2107be79b0e397f93a664931 100644 (file)
@@ -296,6 +296,11 @@ int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags)
     EVP_RAND_CTX *pctx;
     int use_df;
 
+    RAND_DRBG_get_entropy_fn get_entropy = drbg->get_entropy;
+    RAND_DRBG_cleanup_entropy_fn cleanup_entropy = drbg->cleanup_entropy;
+    RAND_DRBG_get_nonce_fn get_nonce = drbg->get_nonce;
+    RAND_DRBG_cleanup_nonce_fn cleanup_nonce = drbg->cleanup_nonce;
+
     if (type == 0 && flags == 0) {
         type = rand_drbg_type[RAND_DRBG_TYPE_PRIMARY];
         flags = rand_drbg_flags[RAND_DRBG_TYPE_PRIMARY];
@@ -344,6 +349,14 @@ int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags)
         RANDerr(0, RAND_R_ERROR_INITIALISING_DRBG);
         goto err;
     }
+
+    if (!RAND_DRBG_set_callbacks(drbg,
+                                 get_entropy, cleanup_entropy,
+                                 get_nonce, cleanup_nonce)) {
+        RANDerr(0, RAND_R_ERROR_INITIALISING_DRBG);
+        goto err;
+    }
+
     return 1;
 err:
     EVP_RAND_CTX_free(drbg->rand);