Add mbedtls_platform_memmove() as a secured memcmp()

Signed-off-by: Piotr Nowicki <piotr.nowicki@arm.com>
diff --git a/library/bignum.c b/library/bignum.c
index 00df10d..2cc8e22 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -558,7 +558,11 @@
         length++;
     } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
 
-    memmove( *p, p_end, length );
+    if( 0 != mbedtls_platform_memmove( *p, p_end, length ) )
+    {
+        ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
+        goto cleanup;
+    }
     *p += length;
 
 cleanup:
diff --git a/library/nist_kw.c b/library/nist_kw.c
index 0ad270a..5b5aa1c 100644
--- a/library/nist_kw.c
+++ b/library/nist_kw.c
@@ -222,7 +222,10 @@
         }
 
         mbedtls_platform_memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
-        memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
+        if( 0 != mbedtls_platform_memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ) )
+        {
+            return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
+        }
     }
     else
     {
@@ -343,7 +346,11 @@
     }
 
     mbedtls_platform_memcpy( A, input, KW_SEMIBLOCK_LENGTH );
-    memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+    if( 0 != mbedtls_platform_memmove( output, input + KW_SEMIBLOCK_LENGTH,
+                                       ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ) )
+    {
+        return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
+    }
 
     /* Calculate intermediate values */
     for( t = s; t >= 1; t-- )
diff --git a/library/pk.c b/library/pk.c
index 8557513..f2df7db 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -629,7 +629,10 @@
 
     len = n_len;
     *p -= len;
-    memmove( *p, start, len );
+    if( 0 != mbedtls_platform_memmove( *p, start, len ) )
+    {
+        return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+    }
 
     /* 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 +694,11 @@
     *--p = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE;
     len += 2;
 
+    if( 0 != mbedtls_platform_memmove( sig, p, len ) )
+    {
+        return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+    }
     ret = 0;
-    memmove( sig, p, len );
     *sig_len = len;
 
     return( ret );
diff --git a/library/platform_util.c b/library/platform_util.c
index 3869f30..694e23a 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 -1;
+}
+
 int mbedtls_platform_memcmp( const void *buf1, const void *buf2, size_t num )
 {
     volatile const unsigned char *A = (volatile const unsigned char *) buf1;