Support set *_drbg reseed interval before seed

mbedtls_ctr_drbg_set_reseed_interval() and
mbedtls_hmac_drbg_set_reseed_interval() can now be called before
their seed functions and the reseed_interval value will persist.
Previously it would be overwritten with the default value.

*_drbg_reseed_interval is now set in init() and free().

mbedtls_ctr_drbg_free() and mbedtls_hmac_drbg_free() now
reset the drbg context to the state immediately after init().

Tests:
- Added test to check that DRBG reseeds when reseed_counter
reaches reseed_interval, if reseed_interval set before seed
and reseed_interval is less than MBEDTLS_*_DRBG_RESEED_INTERVAL.

Signed-off-by: gacquroff <gavina352@gmail.com>
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index 7aadaf9..24d9870 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -200,6 +200,11 @@
  *                      and prepares it for mbedtls_ctr_drbg_seed()
  *                      or mbedtls_ctr_drbg_free().
  *
+ * \note                The reseed interval is
+ *                      #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default.
+ *                      You can override it by calling
+ *                      mbedtls_ctr_drbg_set_reseed_interval().
+ *
  * \param ctx           The CTR_DRBG context to initialize.
  */
 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
@@ -280,7 +285,8 @@
                    size_t len );
 
 /**
- * \brief               This function clears CTR_CRBG context data.
+ * \brief               This function resets CTR_DRBG context to the state immediately
+ *                      after initial call of mbedtls_ctr_drbg_init().
  *
  * \param ctx           The CTR_DRBG context to clear.
  */
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index 289cf48..cd23a16 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -138,6 +138,10 @@
  * This function makes the context ready for mbedtls_hmac_drbg_seed(),
  * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free().
  *
+ * \note                The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL
+ *                      by default. Override this value by calling
+ *                      mbedtls_hmac_drbg_set_reseed_interval().
+ *
  * \param ctx           HMAC_DRBG context to be initialized.
  */
 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
@@ -378,7 +382,8 @@
 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
 
 /**
- * \brief               Free an HMAC_DRBG context
+ * \brief               This function resets HMAC_DRBG context to the state immediately
+ *                      after initial call of mbedtls_hmac_drbg_init().
  *
  * \param ctx           The HMAC_DRBG context to free.
  */
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 184e09f..bc5cc8f 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -86,11 +86,17 @@
 {
     memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
 
+    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
+
 #if defined(MBEDTLS_THREADING_C)
     mbedtls_mutex_init( &ctx->mutex );
 #endif
 }
 
+/*
+ *  This function resets CTR_DRBG context to the state immediately
+ *  after initial call of mbedtls_ctr_drbg_init().
+ */
 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
 {
     if( ctx == NULL )
@@ -101,6 +107,10 @@
 #endif
     mbedtls_aes_free( &ctx->aes_ctx );
     mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
+    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
 }
 
 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
@@ -379,7 +389,6 @@
 
     if( ctx->entropy_len == 0 )
         ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
-    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
 
     /*
      * Initialize with an empty key
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index f24a66c..26b15e9 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -87,6 +87,8 @@
 {
     memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
 
+    ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
+
 #if defined(MBEDTLS_THREADING_C)
     mbedtls_mutex_init( &ctx->mutex );
 #endif
@@ -298,8 +300,6 @@
     ctx->f_entropy = f_entropy;
     ctx->p_entropy = p_entropy;
 
-    ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-
     if( ctx->entropy_len == 0 )
     {
         /*
@@ -444,7 +444,8 @@
 }
 
 /*
- * Free an HMAC_DRBG context
+ *  This function resets HMAC_DRBG context to the state immediately
+ *  after initial call of mbedtls_hmac_drbg_init().
  */
 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
 {
@@ -456,6 +457,10 @@
 #endif
     mbedtls_md_free( &ctx->md_ctx );
     mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
+    ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
 }
 
 #if defined(MBEDTLS_FS_IO)
diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function
index 134ba9c..13669e5 100644
--- a/tests/suites/test_suite_ctr_drbg.function
+++ b/tests/suites/test_suite_ctr_drbg.function
@@ -145,13 +145,16 @@
     memset( out, 0, sizeof( out ) );
     memset( add, 0, sizeof( add ) );
 
+    /* Set reseed interval before seed */
+    mbedtls_ctr_drbg_set_reseed_interval( &ctx, 2 * reps );
+
     /* Init must use entropy */
     last_idx = test_offset_idx;
     TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, mbedtls_test_entropy_func, entropy, NULL, 0 ) == 0 );
     TEST_ASSERT( last_idx < test_offset_idx );
 
-    /* By default, PR is off and reseed_interval is large,
-     * so the next few calls should not use entropy */
+    /* By default, PR is off, and reseed interval was set to
+     * 2 * reps so the next few calls should not use entropy */
     last_idx = test_offset_idx;
     for( i = 0; i < reps; i++ )
     {
@@ -167,15 +170,16 @@
     TEST_ASSERT( out[sizeof( out ) - 2] == 0 );
     TEST_ASSERT( out[sizeof( out ) - 1] == 0 );
 
-    /* Set reseed_interval to the number of calls done,
-     * so the next call should reseed */
-    mbedtls_ctr_drbg_set_reseed_interval( &ctx, 2 * reps );
+    /* There have been 2 * reps calls to random. The next call should reseed */
     TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
     TEST_ASSERT( last_idx < test_offset_idx );
 
-    /* The new few calls should not reseed */
+    /* Set reseed interval after seed */
+    mbedtls_ctr_drbg_set_reseed_interval( &ctx, 4 * reps + 1 );
+
+    /* The next few calls should not reseed */
     last_idx = test_offset_idx;
-    for( i = 0; i < reps / 2; i++ )
+    for( i = 0; i < (2 * reps); i++ )
     {
         TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
         TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) ,
diff --git a/tests/suites/test_suite_hmac_drbg.function b/tests/suites/test_suite_hmac_drbg.function
index a413f5e..dd8ac9a 100644
--- a/tests/suites/test_suite_hmac_drbg.function
+++ b/tests/suites/test_suite_hmac_drbg.function
@@ -48,14 +48,17 @@
     md_info = mbedtls_md_info_from_type( md_alg );
     TEST_ASSERT( md_info != NULL );
 
+    /* Set reseed interval before seed */
+    mbedtls_hmac_drbg_set_reseed_interval( &ctx, 2 * reps );
+
     /* Init must use entropy */
     last_len = entropy.len;
     TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &entropy,
                                  NULL, 0 ) == 0 );
     TEST_ASSERT( entropy.len < last_len );
 
-    /* By default, PR is off and reseed_interval is large,
-     * so the next few calls should not use entropy */
+    /* By default, PR is off, and reseed interval was set to
+     * 2 * reps so the next few calls should not use entropy */
     last_len = entropy.len;
     for( i = 0; i < reps; i++ )
     {
@@ -71,15 +74,16 @@
     TEST_ASSERT( out[sizeof( out ) - 2] == 0 );
     TEST_ASSERT( out[sizeof( out ) - 1] == 0 );
 
-    /* Set reseed_interval to the number of calls done,
-     * so the next call should reseed */
-    mbedtls_hmac_drbg_set_reseed_interval( &ctx, 2 * reps );
+    /* There have been 2 * reps calls to random. The next call should reseed */
     TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
     TEST_ASSERT( entropy.len < last_len );
 
+    /* Set reseed interval after seed */
+    mbedtls_hmac_drbg_set_reseed_interval( &ctx, 4 * reps + 1);
+
     /* The new few calls should not reseed */
     last_len = entropy.len;
-    for( i = 0; i < reps / 2; i++ )
+    for( i = 0; i < (2 * reps); i++ )
     {
         TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
         TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) ,
@@ -200,7 +204,7 @@
     TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, out_len,
                                             add2, add2_len ) == 0 );
 
-    /* clear for second run */
+    /* Reset context for second run */
     mbedtls_hmac_drbg_free( &ctx );
 
     TEST_ASSERT( memcmp( my_output, output, out_len ) == 0 );