rand_lib.c: fix null pointer dereferences after RAND_get_rand_method() failure
authorDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Wed, 11 Dec 2019 21:41:00 +0000 (07:41 +1000)
committerPauli <paul.dale@oracle.com>
Wed, 11 Dec 2019 21:41:00 +0000 (07:41 +1000)
RAND_get_rand_method() can return a NULL method pointer in the case of a
malloc failure, so don't dereference it without a check.

Reported-by: Zu-Ming Jiang (detected by FIFUZZ)
Fixes #10480

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

crypto/err/openssl.txt
crypto/rand/rand_lib.c
include/openssl/randerr.h

index 7a80a7e145dfda19a74a7728dc7631f97cddd5e1..a39b65382d46790c453d8f1cd2e83547d6c541c6 100644 (file)
@@ -1150,6 +1150,8 @@ RAND_F_RAND_POOL_ATTACH:124:rand_pool_attach
 RAND_F_RAND_POOL_BYTES_NEEDED:115:rand_pool_bytes_needed
 RAND_F_RAND_POOL_GROW:127:
 RAND_F_RAND_POOL_NEW:116:rand_pool_new
+RAND_F_RAND_PRIV_BYTES_EX:128:
+RAND_F_RAND_PSEUDO_BYTES:129:
 RAND_F_RAND_WRITE_FILE:112:RAND_write_file
 RSA_F_CHECK_PADDING_MD:140:check_padding_md
 RSA_F_ENCODE_PKCS1:146:encode_pkcs1
index c6b4ad3ae4d40c7a5a9bd9701dc8a149a654e55f..0be9db1c5fc9b55fa278ccef18c7164bd163de13 100644 (file)
@@ -311,6 +311,9 @@ int RAND_poll(void)
 
     const RAND_METHOD *meth = RAND_get_rand_method();
 
+    if (meth == NULL)
+        return 0;
+
     if (meth == RAND_OpenSSL()) {
         /* fill random pool and seed the master DRBG */
         RAND_DRBG *drbg = RAND_DRBG_get0_master();
@@ -831,7 +834,7 @@ void RAND_seed(const void *buf, int num)
 {
     const RAND_METHOD *meth = RAND_get_rand_method();
 
-    if (meth->seed != NULL)
+    if (meth != NULL && meth->seed != NULL)
         meth->seed(buf, num);
 }
 
@@ -839,7 +842,7 @@ void RAND_add(const void *buf, int num, double randomness)
 {
     const RAND_METHOD *meth = RAND_get_rand_method();
 
-    if (meth->add != NULL)
+    if (meth != NULL && meth->add != NULL)
         meth->add(buf, num, randomness);
 }
 
@@ -851,18 +854,20 @@ void RAND_add(const void *buf, int num, double randomness)
 int rand_priv_bytes_ex(OPENSSL_CTX *ctx, unsigned char *buf, int num)
 {
     RAND_DRBG *drbg;
-    int ret;
     const RAND_METHOD *meth = RAND_get_rand_method();
 
-    if (meth != RAND_OpenSSL())
-        return meth->bytes(buf, num);
+    if (meth != NULL && meth != RAND_OpenSSL()) {
+        if (meth->bytes != NULL)
+            return meth->bytes(buf, num);
+        RANDerr(RAND_F_RAND_PRIV_BYTES_EX, RAND_R_FUNC_NOT_IMPLEMENTED);
+        return -1;
+    }
 
     drbg = OPENSSL_CTX_get0_private_drbg(ctx);
-    if (drbg == NULL)
-        return 0;
+    if (drbg != NULL)
+        return RAND_DRBG_bytes(drbg, buf, num);
 
-    ret = RAND_DRBG_bytes(drbg, buf, num);
-    return ret;
+    return 0;
 }
 
 int RAND_priv_bytes(unsigned char *buf, int num)
@@ -873,10 +878,9 @@ int RAND_priv_bytes(unsigned char *buf, int num)
 int rand_bytes_ex(OPENSSL_CTX *ctx, unsigned char *buf, int num)
 {
     RAND_DRBG *drbg;
-    int ret;
     const RAND_METHOD *meth = RAND_get_rand_method();
 
-    if (meth != RAND_OpenSSL()) {
+    if (meth != NULL && meth != RAND_OpenSSL()) {
         if (meth->bytes != NULL)
             return meth->bytes(buf, num);
         RANDerr(RAND_F_RAND_BYTES_EX, RAND_R_FUNC_NOT_IMPLEMENTED);
@@ -884,11 +888,10 @@ int rand_bytes_ex(OPENSSL_CTX *ctx, unsigned char *buf, int num)
     }
 
     drbg = OPENSSL_CTX_get0_public_drbg(ctx);
-    if (drbg == NULL)
-        return 0;
+    if (drbg != NULL)
+        return RAND_DRBG_bytes(drbg, buf, num);
 
-    ret = RAND_DRBG_bytes(drbg, buf, num);
-    return ret;
+    return 0;
 }
 
 int RAND_bytes(unsigned char *buf, int num)
@@ -901,8 +904,9 @@ int RAND_pseudo_bytes(unsigned char *buf, int num)
 {
     const RAND_METHOD *meth = RAND_get_rand_method();
 
-    if (meth->pseudorand != NULL)
+    if (meth != NULL && meth->pseudorand != NULL)
         return meth->pseudorand(buf, num);
+    RANDerr(RAND_F_RAND_PSEUDO_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED);
     return -1;
 }
 #endif
@@ -911,7 +915,7 @@ int RAND_status(void)
 {
     const RAND_METHOD *meth = RAND_get_rand_method();
 
-    if (meth->status != NULL)
+    if (meth != NULL && meth->status != NULL)
         return meth->status();
     return 0;
 }
index e633260712bbd7caa299fdd8c57957d0c964bcf5..68992d771db09e6e6cdb46db475974e635b53095 100644 (file)
@@ -57,6 +57,8 @@ int ERR_load_RAND_strings(void);
 #  define RAND_F_RAND_POOL_BYTES_NEEDED                    0
 #  define RAND_F_RAND_POOL_GROW                            0
 #  define RAND_F_RAND_POOL_NEW                             0
+#  define RAND_F_RAND_PRIV_BYTES_EX                        0
+#  define RAND_F_RAND_PSEUDO_BYTES                         0
 #  define RAND_F_RAND_WRITE_FILE                           0
 # endif