Merge pull request #3448 from piotr-now/platform_util

Renamed mbedtls_platform_memcmp() to mbedtls_platform_memequal()
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index 6990be0..cb7d726 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -87,6 +87,9 @@
 {
     int nr;                     /*!< The number of rounds. */
     uint32_t *rk;               /*!< AES round keys. */
+#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES)
+    uint32_t frk[8];            /*!< Fake AES round keys. */
+#endif
 #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C)
     uint32_t buf[44];           /*!< Unaligned data buffer */
 #else /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index eec05e4..19a7c44 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -77,6 +77,9 @@
 #define MBEDTLS_HMAC_DRBG_PR_OFF   0x55555555   /**< No prediction resistance       */
 #define MBEDTLS_HMAC_DRBG_PR_ON    0x2AAAAAAA   /**< Prediction resistance enabled  */
 
+#define MBEDTLS_HMAC_DRBG_RESEED    0x78547854   /**< Default environment, reseeding enabled */
+#define MBEDTLS_HMAC_DRBG_NO_RESEED 0x07AB87F0   /**< Reseeding disabled, no f_entropy required */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -91,7 +94,7 @@
     mbedtls_md_context_t md_ctx;                    /*!< HMAC context (inc. K)  */
     unsigned char V[MBEDTLS_MD_MAX_SIZE];  /*!< V in the spec          */
     int reseed_counter;                     /*!< reseed counter         */
-
+    int reseed_flag;  /*!< disables reseeding if set to MBEDTLS_HMAC_DRBG_NO_RESEED */
     /* Administrative state */
     size_t entropy_len;         /*!< entropy bytes grabbed on each (re)seed */
     int prediction_resistance;  /*!< enable prediction resistance (Automatic
@@ -221,6 +224,20 @@
                                           int resistance );
 
 /**
+ * \brief               This function turns reseeding on or off.
+ *                      Default value is on.
+ *
+ * \note                If set to MBEDTLS_HMAC_DRBG_NO_RESEED, this function
+ *                      disables reseeding, providing a no_reseed environment.
+ *                      f_entropy can then be null.
+ *
+ * \param ctx           The HMAC_DRBG context.
+ * \param reseed_flag   #MBEDTLS_HMAC_DRBG_NO_RESEED or #MBEDTLS_HMAC_DRBG_RESEED
+ */
+void mbedtls_hmac_drbg_set_reseeding( mbedtls_hmac_drbg_context *ctx,
+                                      int reseed_flag );
+
+/**
  * \brief               This function sets the amount of entropy grabbed on each
  *                      seed or reseed.
  *
@@ -228,9 +245,11 @@
  *
  * \param ctx           The HMAC_DRBG context.
  * \param len           The amount of entropy to grab, in bytes.
+ *
+ * \return              \c 0 if \p len is valid, MBEDTLS_HMAC_DRBG_MAX_INPUT otherwise.
  */
-void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx,
-                                size_t len );
+int mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx,
+                                       size_t len );
 
 /**
  * \brief               Set the reseed interval.
diff --git a/library/aes.c b/library/aes.c
index e9e7544..e7a888f 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -675,6 +675,18 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
+#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES)
+static void mbedtls_generate_fake_key( unsigned int keybits, mbedtls_aes_context *ctx )
+{
+    unsigned int qword;
+
+    for( qword = keybits >> 5; qword > 0; qword-- )
+    {
+        ctx->frk[ qword - 1 ] = mbedtls_platform_random_uint32();
+    }
+}
+#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */
+
 /*
  * AES key schedule (encryption)
  */
@@ -719,6 +731,9 @@
     else
 #endif
     ctx->rk = RK = ctx->buf;
+#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES)
+    mbedtls_generate_fake_key( keybits, ctx );
+#endif
 
 #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
     if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
@@ -858,6 +873,9 @@
     else
 #endif
     ctx->rk = RK = ctx->buf;
+#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES)
+    mbedtls_generate_fake_key( keybits, ctx );
+#endif
 
     /* Also checks keybits */
     if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 )
@@ -1071,7 +1089,8 @@
     uint8_t round_ctrl_table[( 14 + AES_SCA_CM_ROUNDS + 2 )];
 
     aes_data_real.rk_ptr = ctx->rk;
-    aes_data_fake.rk_ptr = ctx->rk;
+    aes_data_fake.rk_ptr = ctx->frk;
+
     aes_data_table[0] = &aes_data_real;
     aes_data_table[1] = &aes_data_fake;
 
@@ -1351,7 +1370,8 @@
     uint8_t round_ctrl_table[( 14 + AES_SCA_CM_ROUNDS + 2 )];
 
     aes_data_real.rk_ptr = ctx->rk;
-    aes_data_fake.rk_ptr = ctx->rk;
+    aes_data_fake.rk_ptr = ctx->frk;
+
     aes_data_table[0] = &aes_data_real;
     aes_data_table[1] = &aes_data_fake;
 
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 6cfaa08..a0b890d 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -482,6 +482,7 @@
         mbedtls_hmac_drbg_context rng_ctx_blind;
 
         mbedtls_hmac_drbg_init( &rng_ctx_blind );
+        mbedtls_hmac_drbg_set_reseeding( &rng_ctx_blind, MBEDTLS_HMAC_DRBG_NO_RESEED );
         p_rng_blind_det = &rng_ctx_blind;
 
         mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info,
@@ -509,6 +510,7 @@
          * a valid ECDSA signature.
          */
         p_rng_blind_det = p_rng;
+        mbedtls_hmac_drbg_set_reseeding( p_rng_blind_det, MBEDTLS_HMAC_DRBG_NO_RESEED );
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
         /*
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index 58750c8..d8669c3 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -62,6 +62,8 @@
 {
     memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
 
+    ctx->prediction_resistance = MBEDTLS_HMAC_DRBG_PR_OFF;
+    ctx->reseed_flag = MBEDTLS_HMAC_DRBG_RESEED;
 #if defined(MBEDTLS_THREADING_C)
     mbedtls_mutex_init( &ctx->mutex );
 #endif
@@ -210,7 +212,7 @@
     size_t seedlen = 0;
     size_t total_entropy_len;
     int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
-    volatile const unsigned char *additional_dup = additional;
+    const unsigned char * volatile additional_dup = additional;
     volatile size_t len_dup = len;
     int reseed_counter_backup = -1;
 
@@ -388,11 +390,24 @@
 }
 
 /*
+ * Set the reseeding flag
+ */
+void mbedtls_hmac_drbg_set_reseeding( mbedtls_hmac_drbg_context *ctx,
+                                      int reseed_flag )
+{
+    ctx->reseed_flag = reseed_flag;
+}
+
+/*
  * Set entropy length grabbed for seeding
  */
-void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
+int mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
 {
+    if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
+        return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+
     ctx->entropy_len = len;
+    return 0;
 }
 
 /*
@@ -417,7 +432,7 @@
     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
     size_t md_len = mbedtls_md_get_size(
         mbedtls_md_get_handle( &ctx->md_ctx ) );
-    size_t left = out_len;
+    volatile size_t left = out_len;
     unsigned char *out = output;
 
     /* II. Check request length */
@@ -429,14 +444,20 @@
         return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
 
     /* 1. (aka VII and IX) Check reseed counter and PR */
-    if( ctx->f_entropy != NULL && /* For no-reseeding instances */
+    if( ctx->reseed_flag != MBEDTLS_HMAC_DRBG_NO_RESEED &&
         ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
           ctx->reseed_counter > ctx->reseed_interval ) )
     {
-        if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
-            return( ret );
-
-        add_len = 0; /* VII.4 */
+            if( ctx->f_entropy == NULL )
+            {
+                return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
+            }
+            else
+            {
+                if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+                    return( ret );
+                add_len = 0; /* VII.4 */
+            }
     }
 
     /* 2. Use additional data if any */
diff --git a/tests/suites/test_suite_hmac_drbg.function b/tests/suites/test_suite_hmac_drbg.function
index da280db..b812b70 100644
--- a/tests/suites/test_suite_hmac_drbg.function
+++ b/tests/suites/test_suite_hmac_drbg.function
@@ -94,12 +94,12 @@
     TEST_ASSERT( entropy.len < last_len );
 
     /* Finally, check setting entropy_len */
-    mbedtls_hmac_drbg_set_entropy_len( &ctx, 42 );
+    TEST_ASSERT( mbedtls_hmac_drbg_set_entropy_len( &ctx, 42 ) == 0 );
     last_len = entropy.len;
     TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
     TEST_ASSERT( (int) last_len - entropy.len == 42 );
 
-    mbedtls_hmac_drbg_set_entropy_len( &ctx, 13 );
+    TEST_ASSERT( mbedtls_hmac_drbg_set_entropy_len( &ctx, 13 ) == 0 );
     last_len = entropy.len;
     TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
     TEST_ASSERT( (int) last_len - entropy.len == 13 );
@@ -149,6 +149,7 @@
     TEST_ASSERT( mbedtls_hmac_drbg_seed_buf( &ctx, md_info, buf, sizeof( buf ) ) == 0 );
 
     /* Make sure it never tries to reseed (would segfault otherwise) */
+    mbedtls_hmac_drbg_set_reseeding( &ctx, MBEDTLS_HMAC_DRBG_NO_RESEED );
     mbedtls_hmac_drbg_set_reseed_interval( &ctx, 3 );
     mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
 
@@ -172,7 +173,7 @@
     mbedtls_hmac_drbg_context ctx;
 
     mbedtls_hmac_drbg_init( &ctx );
-
+    mbedtls_hmac_drbg_set_reseeding( &ctx, MBEDTLS_HMAC_DRBG_NO_RESEED );
     p_entropy.p = entropy->x;
     p_entropy.len = entropy->len;
 
@@ -219,6 +220,7 @@
     mbedtls_hmac_drbg_context ctx;
 
     mbedtls_hmac_drbg_init( &ctx );
+    mbedtls_hmac_drbg_set_reseeding( &ctx, MBEDTLS_HMAC_DRBG_NO_RESEED );
 
     p_entropy.p = entropy->x;
     p_entropy.len = entropy->len;