Merge pull request #3408 from AndrzejKurek/hamming-distance-improvements

Hamming distance improvements
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index a52f9f5..9696f17 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -86,7 +86,7 @@
  * CHACHA20  3                  0x0051-0x0055
  * POLY1305  3                  0x0057-0x005B
  * CHACHAPOLY 2 0x0054-0x0056
- * PLATFORM  3  0x0070-0x0072   0x0071-0x0071
+ * PLATFORM  4  0x0070-0x0072   0x0071-0x0071 0x0076-0x0076
  *
  * High-level module nr (3 bits - 0x0...-0x7...)
  * Name      ID  Nr of Errors
diff --git a/include/mbedtls/nist_kw.h b/include/mbedtls/nist_kw.h
index 3b67b59..c94c15a 100644
--- a/include/mbedtls/nist_kw.h
+++ b/include/mbedtls/nist_kw.h
@@ -133,6 +133,7 @@
  *
  * \return          \c 0 on success.
  * \return          \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
+ * \return          \c MBEDTLS_ERR_PLATFORM_ALLOC_FAILED in case of a memory allocation failure.
  * \return          cipher-specific error code on failure of the underlying cipher.
  */
 int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index ec1df15..8a88ce7 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -42,6 +42,7 @@
 #define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED     -0x0070 /**< Hardware accelerator failed */
 #define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */
 #define MBEDTLS_ERR_PLATFORM_FAULT_DETECTED      -0x0071 /**< A hardware fault was detected in a critical path. As a security precaution this should be treated as a potential physical attack */
+#define MBEDTLS_ERR_PLATFORM_ALLOC_FAILED        -0x0076 /**< Memory allocation failed */
 
 #if defined(MBEDTLS_PLATFORM_C)
 
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index fa9f326..4e0f989 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -199,6 +199,22 @@
 void *mbedtls_platform_memcpy( void *dst, const void *src, size_t num );
 
 /**
+ * \brief       Secure memmove
+ *
+ *              This is a constant-time version of memmove(). It is based on
+ *              the double use of the mbedtls_platform_memcpy() function secured
+ *              against side-channel attacks.
+ *
+ * \param dst   Destination buffer where the data is being moved to.
+ * \param src   Source buffer where the data is being moved from.
+ * \param num   The length of the buffers in bytes.
+ *
+ * \return      0 if the operation was successful
+ * \return      #MBEDTLS_ERR_PLATFORM_ALLOC_FAILED if a memory allocation failed
+ */
+int mbedtls_platform_memmove( void *dst, const void *src, size_t num );
+
+/**
  * \brief       Secure memcmp
  *
  *              This is a constant-time version of memcmp(). If
diff --git a/library/bignum.c b/library/bignum.c
index 00df10d..f4ab0db 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -558,7 +558,7 @@
         length++;
     } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
 
-    memmove( *p, p_end, length );
+    MBEDTLS_MPI_CHK( mbedtls_platform_memmove( *p, p_end, length ) );
     *p += length;
 
 cleanup:
diff --git a/library/error.c b/library/error.c
index ecdec78..893de7f 100644
--- a/library/error.c
+++ b/library/error.c
@@ -843,6 +843,8 @@
         mbedtls_snprintf( buf, buflen, "PLATFORM - The requested feature is not supported by the platform" );
     if( use_ret == -(MBEDTLS_ERR_PLATFORM_FAULT_DETECTED) )
         mbedtls_snprintf( buf, buflen, "PLATFORM - A hardware fault was detected in a critical path. As a security precaution this should be treated as a potential physical attack" );
+    if( use_ret == -(MBEDTLS_ERR_PLATFORM_ALLOC_FAILED) )
+        mbedtls_snprintf( buf, buflen, "PLATFORM - Memory allocation failed" );
 #endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_POLY1305_C)
diff --git a/library/nist_kw.c b/library/nist_kw.c
index 0ad270a..2f7f082 100644
--- a/library/nist_kw.c
+++ b/library/nist_kw.c
@@ -222,7 +222,11 @@
         }
 
         mbedtls_platform_memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
-        memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
+        ret = mbedtls_platform_memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
+        if( ret != 0 )
+        {
+            return ret;
+        }
     }
     else
     {
@@ -343,7 +347,12 @@
     }
 
     mbedtls_platform_memcpy( A, input, KW_SEMIBLOCK_LENGTH );
-    memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+    ret = mbedtls_platform_memmove( output, input + KW_SEMIBLOCK_LENGTH,
+                                       ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+    if( ret != 0 )
+    {
+        return ret;
+    }
 
     /* Calculate intermediate values */
     for( t = s; t >= 1; t-- )
diff --git a/library/pk.c b/library/pk.c
index 8557513..b92eb14 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -46,10 +46,9 @@
 #endif /* MBEDTLS_USE_TINYCRYPT */
 
 #include "mbedtls/platform_util.h"
-
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
+
+#if !defined(MBEDTLS_PLATFORM_C)
 #include <stdlib.h>
 #define mbedtls_calloc    calloc
 #define mbedtls_free       free
@@ -623,13 +622,18 @@
                               size_t n_len )
 {
     size_t len = 0;
+    int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
 
     if( (size_t)( *p - start ) < n_len )
         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
 
     len = n_len;
     *p -= len;
-    memmove( *p, start, len );
+    ret = mbedtls_platform_memmove( *p, start, len );
+    if( ret != 0 )
+    {
+        return( ret );
+    }
 
     /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
      * Neither r nor s should be 0, but as a failsafe measure, still detect
@@ -691,8 +695,11 @@
     *--p = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE;
     len += 2;
 
-    ret = 0;
-    memmove( sig, p, len );
+    ret = mbedtls_platform_memmove( sig, p, len );
+    if( ret != 0 )
+    {
+        return( ret );
+    }
     *sig_len = len;
 
     return( ret );
@@ -1561,7 +1568,7 @@
         }
         else
         {
-            verify_ret = MBEDTLS_ERR_PK_HW_ACCEL_FAILED;
+            verify_ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
         }
     }
 
diff --git a/library/platform_util.c b/library/platform_util.c
index 3869f30..de2fa2b 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -38,6 +38,12 @@
 #include "mbedtls/platform.h"
 #include "mbedtls/threading.h"
 
+#if !defined(MBEDTLS_PLATFORM_C)
+#include <stdlib.h>
+#define mbedtls_calloc    calloc
+#define mbedtls_free       free
+#endif
+
 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
 #include "mbedtls/entropy_poll.h"
 #endif
@@ -121,6 +127,23 @@
     return( memcpy( (void *) dst, (void *) src, start_offset ) );
 }
 
+int mbedtls_platform_memmove( void *dst, const void *src, size_t num )
+{
+    /* The buffers can have a common part, so we cannot do a copy from a random
+     * location. By using a temporary buffer we can do so, but the cost of it
+     * is using more memory and longer transfer time. */
+    void *tmp = mbedtls_calloc( 1, num );
+    if( tmp != NULL )
+    {
+        mbedtls_platform_memcpy( tmp, src, num );
+        mbedtls_platform_memcpy( dst, tmp, num );
+        mbedtls_free( tmp );
+        return 0;
+    }
+
+    return MBEDTLS_ERR_PLATFORM_ALLOC_FAILED;
+}
+
 int mbedtls_platform_memcmp( const void *buf1, const void *buf2, size_t num )
 {
     volatile const unsigned char *A = (volatile const unsigned char *) buf1;
@@ -190,6 +213,9 @@
     do
     {
         i++;
+        /* Dummy calculations to increase the time between iterations and
+         * make side channel attack more difficult by reducing predictability
+         * of its behaviour */
         shift = rn_2 & 0x07;
         if ( i % 2 )
             rn_2 = (uint32_t)( rn_2 >> shift | rn_2 << ( 32 - shift ) );
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index eada831..5c74386 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -27,9 +27,9 @@
 
 #if defined(MBEDTLS_SSL_CLI_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
+
+#if !defined(MBEDTLS_PLATFORM_C)
 #include <stdlib.h>
 #define mbedtls_calloc    calloc
 #define mbedtls_free      free
@@ -724,6 +724,10 @@
             ssl->handshake->hello_random_set = MBEDTLS_SSL_FI_FLAG_SET;
             return( 0 );
         }
+        else
+        {
+            ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
+        }
     }
 
     return( ret );
@@ -2388,6 +2392,10 @@
             ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET;
             return( 0 );
         }
+        else
+        {
+            ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
+        }
     }
 
     MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret );
@@ -2460,6 +2468,12 @@
         {
             ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET;
         }
+        else
+        {
+            ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
+            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret );
+            goto cleanup;
+        }
     }
     else
     {
@@ -3101,7 +3115,7 @@
             }
             else
             {
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+                return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
             }
         }
 #if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index fbad37b..2cd34b2 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -27,9 +27,9 @@
 
 #if defined(MBEDTLS_SSL_SRV_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
+
+#if !defined(MBEDTLS_PLATFORM_C)
 #include <stdlib.h>
 #define mbedtls_calloc    calloc
 #define mbedtls_free      free
@@ -4659,6 +4659,10 @@
             MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
             goto exit;
         }
+        else
+        {
+            ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
+        }
 
     }
 
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index c79fe7d..4f41ac9 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2029,8 +2029,9 @@
             }
             else
             {
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
-                return( ret );
+                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret",
+                                       MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
+                return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
             }
         }
         else
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 7f689ff..43bb977 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -2936,7 +2936,7 @@
  *
  * Return value:
  *  - 0 on success
- *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
+ *  - MBEDTLS_ERR_ECP_IN_PROGRESS or MBEDTLS_ERR_PLATFORM_FAULT_DETECTED otherwise
  */
 static int x509_crt_find_parent_in(
                         mbedtls_x509_crt_sig_info const *child_sig,
@@ -3051,6 +3051,8 @@
             mbedtls_platform_random_delay();
             if( ret_fi == 0 )
                 signature_is_good = X509_SIGNATURE_IS_GOOD;
+            else
+                return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
         }
 
         if( top && ! signature_is_good )
@@ -3869,6 +3871,8 @@
         mbedtls_platform_random_delay();
         if( flags_fi == 0 )
             return( 0 );
+        else
+            return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
     }
 
     /* Preserve the API by removing internal extra bits - from now on the