Make xxx_drbg_random() thread-safe
diff --git a/ChangeLog b/ChangeLog
index 0b3735c..4011512 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -94,6 +94,10 @@
    * ssl_set_bio_timeout() was removed, split into mbedtls_ssl_set_bio() with
      new prototype, and mbedtls_ssl_set_read_timeout().
 
+Changes
+   * mbedtls_ctr_drbg_random() and mbedtls_hmac_drbg_random() are now
+     thread-safe if MBEDTLS_THREADING_C is enabled.
+
 = mbed TLS 1.3 branch
 
 Security
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index 3ea4af2..cebf43b 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -26,6 +26,10 @@
 
 #include "aes.h"
 
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
+
 #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED        -0x0034  /**< The entropy source failed. */
 #define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG              -0x0036  /**< Too many random requested in single call. */
 #define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG                -0x0038  /**< Input too large (Entropy + additional). */
@@ -99,6 +103,10 @@
     int (*f_entropy)(void *, unsigned char *, size_t);
 
     void *p_entropy;            /*!<  context for the entropy function */
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_threading_mutex_t mutex;
+#endif
 }
 mbedtls_ctr_drbg_context;
 
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index fb2ee0e..eeac3e3 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -26,6 +26,10 @@
 
 #include "md.h"
 
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
+
 /*
  * Error codes
  */
@@ -87,6 +91,10 @@
     /* Callbacks */
     int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */
     void *p_entropy;            /*!< context for the entropy function        */
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_threading_mutex_t mutex;
+#endif
 } mbedtls_hmac_drbg_context;
 
 /**
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index ec7d9a7..54feb71 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -61,6 +61,10 @@
 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
 }
 
 /*
@@ -115,6 +119,9 @@
     if( ctx == NULL )
         return;
 
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_free( &ctx->mutex );
+#endif
     mbedtls_aes_free( &ctx->aes_ctx );
     mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
 }
@@ -392,7 +399,22 @@
 
 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
 {
-    return mbedtls_ctr_drbg_random_with_add( p_rng, output, output_len, NULL, 0 );
+    int ret;
+    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
+
+#if defined(MBEDTLS_THREADING_C)
+    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
 }
 
 #if defined(MBEDTLS_FS_IO)
@@ -537,6 +559,8 @@
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
     CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
 
+    mbedtls_ctr_drbg_free( &ctx );
+
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
 
@@ -546,6 +570,8 @@
     if( verbose != 0 )
         mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
 
+    mbedtls_ctr_drbg_init( &ctx );
+
     test_offset = 0;
     CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
                             (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
@@ -554,6 +580,8 @@
     CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
     CHK( memcmp( buf, result_nopr, 16 ) );
 
+    mbedtls_ctr_drbg_free( &ctx );
+
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
 
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index 710eb84..02fcc7d 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -62,6 +62,10 @@
 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
 }
 
 /*
@@ -313,7 +317,22 @@
  */
 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
 {
-    return( mbedtls_hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
+    int ret;
+    mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
+
+#if defined(MBEDTLS_THREADING_C)
+    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
 }
 
 /*
@@ -324,8 +343,10 @@
     if( ctx == NULL )
         return;
 
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_free( &ctx->mutex );
+#endif
     mbedtls_md_free( &ctx->md_ctx );
-
     mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
 }
 
@@ -481,6 +502,8 @@
     CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
     mbedtls_hmac_drbg_free( &ctx );
 
+    mbedtls_hmac_drbg_free( &ctx );
+
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
 
@@ -490,6 +513,8 @@
     if( verbose != 0 )
         mbedtls_printf( "  HMAC_DRBG (PR = False) : " );
 
+    mbedtls_hmac_drbg_init( &ctx );
+
     test_offset = 0;
     CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
                          hmac_drbg_self_test_entropy, (void *) entropy_nopr,
@@ -500,6 +525,8 @@
     CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
     mbedtls_hmac_drbg_free( &ctx );
 
+    mbedtls_hmac_drbg_free( &ctx );
+
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );