Merge remote-tracking branch 'upstream-restricted/pr/421' into development-proposed
diff --git a/ChangeLog b/ChangeLog
index d1a69b7..7b50534 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 mbed TLS ChangeLog (Sorted per branch, date)
 
+= mbed TLS x.x.x branch released xxxx-xx-xx
+
+API Changes
+   * Extend the platform module with a util component that contains
+     functionality shared by multiple Mbed TLS modules. At this stage
+     platform_util.h (and its associated platform_util.c) only contain
+     mbedtls_platform_zeroize(), which is a critical function from a security
+     point of view. mbedtls_platform_zeroize() needs to be regularly tested
+     against compilers to ensure that calls to it are not removed from the
+     output binary as part of redundant code elimination optimizations.
+     Therefore, mbedtls_platform_zeroize() is moved to the platform module to
+     facilitate testing and maintenance.
+
 = mbed TLS 2.9.0 branch released 2018-04-30
 
 Security
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 9585e69..7c9acb2 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -2852,6 +2852,26 @@
  */
 #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
 
+/**
+ * Uncomment the macro to let mbed TLS use your alternate implementation of
+ * mbedtls_platform_zeroize(). This replaces the default implementation in
+ * platform_util.c.
+ *
+ * mbedtls_platform_zeroize() is a widely used function across the library to
+ * zero a block of memory. The implementation is expected to be secure in the
+ * sense that it has been written to prevent the compiler from removing calls
+ * to mbedtls_platform_zeroize() as part of redundant code elimination
+ * optimizations. However, it is difficult to guarantee that calls to
+ * mbedtls_platform_zeroize() will not be optimized by the compiler as older
+ * versions of the C language standards do not provide a secure implementation
+ * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to
+ * configure their own implementation of mbedtls_platform_zeroize(), for
+ * example by using directives specific to their compiler, features from newer
+ * C standards (e.g using memset_s() in C11) or calling a secure memset() from
+ * their system (e.g explicit_bzero() in BSD).
+ */
+//#define MBEDTLS_PLATFORM_ZEROIZE_ALT
+
 /* \} name SECTION: Customisation configuration options */
 
 /* Target and application specific configurations */
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
new file mode 100644
index 0000000..84f0732
--- /dev/null
+++ b/include/mbedtls/platform_util.h
@@ -0,0 +1,62 @@
+/**
+ * \file platform_util.h
+ *
+ * \brief Common and shared functions used by multiple modules in the Mbed TLS
+ *        library.
+ */
+/*
+ *  Copyright (C) 2018, Arm Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_PLATFORM_UTIL_H
+#define MBEDTLS_PLATFORM_UTIL_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief       Securely zeroize a buffer
+ *
+ *              The function is meant to wipe the data contained in a buffer so
+ *              that it can no longer be recovered even if the program memory
+ *              is later compromised. Call this function on sensitive data
+ *              stored on the stack before returning from a function, and on
+ *              sensitive data stored on the heap before freeing the heap
+ *              object.
+ *
+ *              It is extremely difficult to guarantee that calls to
+ *              mbedtls_platform_zeroize() are not removed by aggressive
+ *              compiler optimizations in a portable way. For this reason, Mbed
+ *              TLS provides the configuration option
+ *              MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure
+ *              mbedtls_platform_zeroize() to use a suitable implementation for
+ *              their platform and needs
+ *
+ * \param buf   Buffer to be zeroized
+ * \param len   Length of the buffer in bytes
+ *
+ */
+void mbedtls_platform_zeroize( void *buf, size_t len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_PLATFORM_UTIL_H */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index fc3febd..6177ca2 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -46,6 +46,7 @@
     pkparse.c
     pkwrite.c
     platform.c
+    platform_util.c
     ripemd160.c
     rsa.c
     rsa_internal.c
diff --git a/library/Makefile b/library/Makefile
index 97f796f..b155c72 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -62,10 +62,11 @@
 		padlock.o	pem.o		pk.o		\
 		pk_wrap.o	pkcs12.o	pkcs5.o		\
 		pkparse.o	pkwrite.o	platform.o	\
-		ripemd160.o	rsa_internal.o	rsa.o  		\
-		sha1.o		sha256.o	sha512.o	\
-		threading.o	timing.o	version.o	\
-		version_features.o		xtea.o
+		platform_util.o	ripemd160.o	rsa_internal.o	\
+		rsa.o 		sha1.o		sha256.o	\
+		sha512.o	threading.o	timing.o	\
+		version.o	version_features.o		\
+		xtea.o
 
 OBJS_X509=	certs.o		pkcs11.o	x509.o		\
 		x509_create.o	x509_crl.o	x509_crt.o	\
diff --git a/library/aes.c b/library/aes.c
index da94b19..b0aea00 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -36,6 +36,7 @@
 #include <string.h>
 
 #include "mbedtls/aes.h"
+#include "mbedtls/platform_util.h"
 #if defined(MBEDTLS_PADLOCK_C)
 #include "mbedtls/padlock.h"
 #endif
@@ -54,11 +55,6 @@
 
 #if !defined(MBEDTLS_AES_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (little endian)
  */
@@ -522,7 +518,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
 }
 
 /*
diff --git a/library/arc4.c b/library/arc4.c
index 05b33d3..b8998ac 100644
--- a/library/arc4.c
+++ b/library/arc4.c
@@ -33,6 +33,7 @@
 #if defined(MBEDTLS_ARC4_C)
 
 #include "mbedtls/arc4.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -47,11 +48,6 @@
 
 #if !defined(MBEDTLS_ARC4_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 void mbedtls_arc4_init( mbedtls_arc4_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_arc4_context ) );
@@ -62,7 +58,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_arc4_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) );
 }
 
 /*
diff --git a/library/asn1parse.c b/library/asn1parse.c
index 4dd65c0..171c340 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -28,6 +28,7 @@
 #if defined(MBEDTLS_ASN1_PARSE_C)
 
 #include "mbedtls/asn1.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -43,11 +44,6 @@
 #define mbedtls_free       free
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 /*
  * ASN.1 DER decoding routines
  */
@@ -313,7 +309,7 @@
 
     if( *p == end )
     {
-        mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) );
+        mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) );
         return( 0 );
     }
 
@@ -358,7 +354,7 @@
     mbedtls_free( cur->oid.p );
     mbedtls_free( cur->val.p );
 
-    mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) );
+    mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) );
 }
 
 void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head )
diff --git a/library/bignum.c b/library/bignum.c
index f58af78..423e375 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -45,6 +45,7 @@
 
 #include "mbedtls/bignum.h"
 #include "mbedtls/bn_mul.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -58,16 +59,6 @@
 #define mbedtls_free       free
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) {
-    volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0;
-}
-
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 #define ciL    (sizeof(mbedtls_mpi_uint))         /* chars in limb  */
 #define biL    (ciL << 3)               /* bits  in limb  */
 #define biH    (ciL << 2)               /* half limb size */
@@ -81,6 +72,12 @@
 #define BITS_TO_LIMBS(i)  ( (i) / biL + ( (i) % biL != 0 ) )
 #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
 
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
+{
+    mbedtls_platform_zeroize( v, ciL * n );
+}
+
 /*
  * Initialize one MPI
  */
@@ -1897,7 +1894,7 @@
     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
 
 cleanup:
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
     return( ret );
 }
 
diff --git a/library/blowfish.c b/library/blowfish.c
index 9003f0d..5b6bb98 100644
--- a/library/blowfish.c
+++ b/library/blowfish.c
@@ -34,16 +34,12 @@
 #if defined(MBEDTLS_BLOWFISH_C)
 
 #include "mbedtls/blowfish.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
 #if !defined(MBEDTLS_BLOWFISH_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -165,7 +161,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_blowfish_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) );
 }
 
 /*
diff --git a/library/camellia.c b/library/camellia.c
index ac6f96a..41b7da0 100644
--- a/library/camellia.c
+++ b/library/camellia.c
@@ -34,6 +34,7 @@
 #if defined(MBEDTLS_CAMELLIA_C)
 
 #include "mbedtls/camellia.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -48,11 +49,6 @@
 
 #if !defined(MBEDTLS_CAMELLIA_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -333,7 +329,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_camellia_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) );
 }
 
 /*
diff --git a/library/ccm.c b/library/ccm.c
index 9101e5f..cf65209 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -37,6 +37,7 @@
 #if defined(MBEDTLS_CCM_C)
 
 #include "mbedtls/ccm.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -51,11 +52,6 @@
 
 #if !defined(MBEDTLS_CCM_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 #define CCM_ENCRYPT 0
 #define CCM_DECRYPT 1
 
@@ -102,7 +98,7 @@
 void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
 {
     mbedtls_cipher_free( &ctx->cipher_ctx );
-    mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
 }
 
 /*
@@ -343,7 +339,7 @@
 
     if( diff != 0 )
     {
-        mbedtls_zeroize( output, length );
+        mbedtls_platform_zeroize( output, length );
         return( MBEDTLS_ERR_CCM_AUTH_FAILED );
     }
 
diff --git a/library/cipher.c b/library/cipher.c
index 7369f48..a5cd61c 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -33,6 +33,7 @@
 
 #include "mbedtls/cipher.h"
 #include "mbedtls/cipher_internal.h"
+#include "mbedtls/platform_util.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -60,11 +61,6 @@
 #define MBEDTLS_CIPHER_MODE_STREAM
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 static int supported_init = 0;
 
 const int *mbedtls_cipher_list( void )
@@ -141,7 +137,8 @@
 #if defined(MBEDTLS_CMAC_C)
     if( ctx->cmac_ctx )
     {
-       mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) );
+       mbedtls_platform_zeroize( ctx->cmac_ctx,
+                                 sizeof( mbedtls_cmac_context_t ) );
        mbedtls_free( ctx->cmac_ctx );
     }
 #endif
@@ -149,7 +146,7 @@
     if( ctx->cipher_ctx )
         ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
 
-    mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
+    mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
 }
 
 int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
diff --git a/library/cmac.c b/library/cmac.c
index a4a2106..4d7a1f1 100644
--- a/library/cmac.c
+++ b/library/cmac.c
@@ -49,6 +49,7 @@
 #if defined(MBEDTLS_CMAC_C)
 
 #include "mbedtls/cmac.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -67,11 +68,6 @@
 
 #if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 /*
  * Multiplication by u in the Galois field of GF(2^n)
  *
@@ -144,7 +140,7 @@
     unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
     size_t olen, block_size;
 
-    mbedtls_zeroize( L, sizeof( L ) );
+    mbedtls_platform_zeroize( L, sizeof( L ) );
 
     block_size = ctx->cipher_info->block_size;
 
@@ -162,7 +158,7 @@
         goto exit;
 
 exit:
-    mbedtls_zeroize( L, sizeof( L ) );
+    mbedtls_platform_zeroize( L, sizeof( L ) );
 
     return( ret );
 }
@@ -238,7 +234,7 @@
 
     ctx->cmac_ctx = cmac_ctx;
 
-    mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
+    mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
 
     return 0;
 }
@@ -330,8 +326,8 @@
     block_size = ctx->cipher_info->block_size;
     state = cmac_ctx->state;
 
-    mbedtls_zeroize( K1, sizeof( K1 ) );
-    mbedtls_zeroize( K2, sizeof( K2 ) );
+    mbedtls_platform_zeroize( K1, sizeof( K1 ) );
+    mbedtls_platform_zeroize( K2, sizeof( K2 ) );
     cmac_generate_subkeys( ctx, K1, K2 );
 
     last_block = cmac_ctx->unprocessed_block;
@@ -361,14 +357,14 @@
 exit:
     /* Wipe the generated keys on the stack, and any other transients to avoid
      * side channel leakage */
-    mbedtls_zeroize( K1, sizeof( K1 ) );
-    mbedtls_zeroize( K2, sizeof( K2 ) );
+    mbedtls_platform_zeroize( K1, sizeof( K1 ) );
+    mbedtls_platform_zeroize( K2, sizeof( K2 ) );
 
     cmac_ctx->unprocessed_len = 0;
-    mbedtls_zeroize( cmac_ctx->unprocessed_block,
-                     sizeof( cmac_ctx->unprocessed_block ) );
+    mbedtls_platform_zeroize( cmac_ctx->unprocessed_block,
+                              sizeof( cmac_ctx->unprocessed_block ) );
 
-    mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
+    mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
     return( ret );
 }
 
@@ -383,10 +379,10 @@
 
     /* Reset the internal state */
     cmac_ctx->unprocessed_len = 0;
-    mbedtls_zeroize( cmac_ctx->unprocessed_block,
-                     sizeof( cmac_ctx->unprocessed_block ) );
-    mbedtls_zeroize( cmac_ctx->state,
-                     sizeof( cmac_ctx->state ) );
+    mbedtls_platform_zeroize( cmac_ctx->unprocessed_block,
+                              sizeof( cmac_ctx->unprocessed_block ) );
+    mbedtls_platform_zeroize( cmac_ctx->state,
+                              sizeof( cmac_ctx->state ) );
 
     return( 0 );
 }
@@ -466,7 +462,7 @@
                                output );
 
 exit:
-    mbedtls_zeroize( int_key, sizeof( int_key ) );
+    mbedtls_platform_zeroize( int_key, sizeof( int_key ) );
 
     return( ret );
 }
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index ff532a0..d0e5ba8 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -33,6 +33,7 @@
 #if defined(MBEDTLS_CTR_DRBG_C)
 
 #include "mbedtls/ctr_drbg.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -49,11 +50,6 @@
 #endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST */
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * CTR_DRBG context initialization
  */
@@ -125,7 +121,7 @@
     mbedtls_mutex_free( &ctx->mutex );
 #endif
     mbedtls_aes_free( &ctx->aes_ctx );
-    mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
 }
 
 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
@@ -245,16 +241,16 @@
     /*
     * tidy up the stack
     */
-    mbedtls_zeroize( buf, sizeof( buf ) );
-    mbedtls_zeroize( tmp, sizeof( tmp ) );
-    mbedtls_zeroize( key, sizeof( key ) );
-    mbedtls_zeroize( chain, sizeof( chain ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+    mbedtls_platform_zeroize( key, sizeof( key ) );
+    mbedtls_platform_zeroize( chain, sizeof( chain ) );
     if( 0 != ret )
     {
         /*
         * wipe partial seed from memory
         */
-        mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
+        mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
     }
 
     return( ret );
@@ -493,7 +489,7 @@
         ret = 0;
 
 exit:
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     fclose( f );
     return( ret );
@@ -526,7 +522,7 @@
 
     fclose( f );
 
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     if( ret != 0 )
         return( ret );
diff --git a/library/des.c b/library/des.c
index 09f95cfc..ca9e071 100644
--- a/library/des.c
+++ b/library/des.c
@@ -34,6 +34,7 @@
 #if defined(MBEDTLS_DES_C)
 
 #include "mbedtls/des.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -48,11 +49,6 @@
 
 #if !defined(MBEDTLS_DES_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -316,7 +312,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_des_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) );
 }
 
 void mbedtls_des3_init( mbedtls_des3_context *ctx )
@@ -329,7 +325,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_des3_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) );
 }
 
 static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
@@ -553,7 +549,7 @@
     uint32_t sk[96];
 
     des3_set2key( ctx->sk, sk, key );
-    mbedtls_zeroize( sk,  sizeof( sk ) );
+    mbedtls_platform_zeroize( sk,  sizeof( sk ) );
 
     return( 0 );
 }
@@ -567,7 +563,7 @@
     uint32_t sk[96];
 
     des3_set2key( sk, ctx->sk, key );
-    mbedtls_zeroize( sk,  sizeof( sk ) );
+    mbedtls_platform_zeroize( sk,  sizeof( sk ) );
 
     return( 0 );
 }
@@ -604,7 +600,7 @@
     uint32_t sk[96];
 
     des3_set3key( ctx->sk, sk, key );
-    mbedtls_zeroize( sk,  sizeof( sk ) );
+    mbedtls_platform_zeroize( sk,  sizeof( sk ) );
 
     return( 0 );
 }
@@ -618,7 +614,7 @@
     uint32_t sk[96];
 
     des3_set3key( sk, ctx->sk, key );
-    mbedtls_zeroize( sk,  sizeof( sk ) );
+    mbedtls_platform_zeroize( sk,  sizeof( sk ) );
 
     return( 0 );
 }
diff --git a/library/dhm.c b/library/dhm.c
index 28ac310..82cbb0c 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -36,6 +36,7 @@
 #if defined(MBEDTLS_DHM_C)
 
 #include "mbedtls/dhm.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -58,10 +59,6 @@
 #endif
 
 #if !defined(MBEDTLS_DHM_ALT)
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
 
 /*
  * helper to validate the mbedtls_mpi size and import it
@@ -437,7 +434,7 @@
     mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X  );
     mbedtls_mpi_free( &ctx->G  ); mbedtls_mpi_free( &ctx->P  );
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
 }
 
 #if defined(MBEDTLS_ASN1_PARSE_C)
@@ -575,7 +572,7 @@
     {
         fclose( f );
 
-        mbedtls_zeroize( *buf, *n + 1 );
+        mbedtls_platform_zeroize( *buf, *n + 1 );
         mbedtls_free( *buf );
 
         return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
@@ -605,7 +602,7 @@
 
     ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
 
-    mbedtls_zeroize( buf, n );
+    mbedtls_platform_zeroize( buf, n );
     mbedtls_free( buf );
 
     return( ret );
diff --git a/library/ecp.c b/library/ecp.c
index 92a188b..41db3fb 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -51,6 +51,7 @@
 
 #include "mbedtls/ecp.h"
 #include "mbedtls/threading.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -73,11 +74,6 @@
 #define inline __inline
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 #if defined(MBEDTLS_SELF_TEST)
 /*
  * Counts of point addition and doubling, and field multiplications.
@@ -348,7 +344,7 @@
         mbedtls_free( grp->T );
     }
 
-    mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
+    mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
 }
 
 /*
diff --git a/library/entropy.c b/library/entropy.c
index e17512e..f8db1a5 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -35,6 +35,7 @@
 
 #include "mbedtls/entropy.h"
 #include "mbedtls/entropy_poll.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -59,11 +60,6 @@
 #include "mbedtls/havege.h"
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 #define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */
 
 void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
@@ -140,7 +136,7 @@
     ctx->initial_entropy_run = 0;
 #endif
     ctx->source_count = 0;
-    mbedtls_zeroize( ctx->source, sizeof( ctx->source ) );
+    mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
     ctx->accumulator_started = 0;
 }
 
@@ -232,7 +228,7 @@
 #endif
 
 cleanup:
-    mbedtls_zeroize( tmp, sizeof( tmp ) );
+    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
 
     return( ret );
 }
@@ -300,7 +296,7 @@
         ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
 
 cleanup:
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     return( ret );
 }
@@ -433,7 +429,7 @@
     ret = 0;
 
 exit:
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
 #if defined(MBEDTLS_THREADING_C)
     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
@@ -486,7 +482,7 @@
     ret = 0;
 
 exit:
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     fclose( f );
     return( ret );
@@ -516,7 +512,7 @@
 
     fclose( f );
 
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     if( ret != 0 )
         return( ret );
diff --git a/library/gcm.c b/library/gcm.c
index 294a86d..57b0279 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -38,6 +38,7 @@
 #if defined(MBEDTLS_GCM_C)
 
 #include "mbedtls/gcm.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -80,11 +81,6 @@
 }
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * Initialize a context
  */
@@ -498,7 +494,7 @@
 
     if( diff != 0 )
     {
-        mbedtls_zeroize( output, length );
+        mbedtls_platform_zeroize( output, length );
         return( MBEDTLS_ERR_GCM_AUTH_FAILED );
     }
 
@@ -508,7 +504,7 @@
 void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
 {
     mbedtls_cipher_free( &ctx->cipher_ctx );
-    mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
 }
 
 #endif /* !MBEDTLS_GCM_ALT */
diff --git a/library/havege.c b/library/havege.c
index 2b75ef7..4dcac02 100644
--- a/library/havege.c
+++ b/library/havege.c
@@ -36,14 +36,10 @@
 
 #include "mbedtls/havege.h"
 #include "mbedtls/timing.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /* ------------------------------------------------------------------------
  * On average, one iteration accesses two 8-word blocks in the havege WALK
  * table, and generates 16 words in the RES array.
@@ -208,7 +204,7 @@
     if( hs == NULL )
         return;
 
-    mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) );
+    mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) );
 }
 
 /*
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index 24c609e..dad55ff 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -34,6 +34,7 @@
 #if defined(MBEDTLS_HMAC_DRBG_C)
 
 #include "mbedtls/hmac_drbg.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -50,11 +51,6 @@
 #endif /* MBEDTLS_SELF_TEST */
 #endif /* MBEDTLS_PLATFORM_C */
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * HMAC_DRBG context initialization
  */
@@ -338,7 +334,7 @@
     mbedtls_mutex_free( &ctx->mutex );
 #endif
     mbedtls_md_free( &ctx->md_ctx );
-    mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
 }
 
 #if defined(MBEDTLS_FS_IO)
@@ -364,7 +360,7 @@
 
 exit:
     fclose( f );
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     return( ret );
 }
@@ -396,7 +392,7 @@
 
     fclose( f );
 
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     if( ret != 0 )
         return( ret );
diff --git a/library/md.c b/library/md.c
index 00249af..303cdcb 100644
--- a/library/md.c
+++ b/library/md.c
@@ -33,6 +33,7 @@
 
 #include "mbedtls/md.h"
 #include "mbedtls/md_internal.h"
+#include "mbedtls/platform_util.h"
 
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
@@ -48,11 +49,6 @@
 #include <stdio.h>
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * Reminder: update profiles in x509_crt.c when adding a new hash!
  */
@@ -193,11 +189,12 @@
 
     if( ctx->hmac_ctx != NULL )
     {
-        mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size );
+        mbedtls_platform_zeroize( ctx->hmac_ctx,
+                                  2 * ctx->md_info->block_size );
         mbedtls_free( ctx->hmac_ctx );
     }
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) );
 }
 
 int mbedtls_md_clone( mbedtls_md_context_t *dst,
@@ -311,7 +308,7 @@
         ret = md_info->finish_func( ctx.md_ctx, output );
 
 cleanup:
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
     fclose( f );
     mbedtls_md_free( &ctx );
 
@@ -361,7 +358,7 @@
         goto cleanup;
 
 cleanup:
-    mbedtls_zeroize( sum, sizeof( sum ) );
+    mbedtls_platform_zeroize( sum, sizeof( sum ) );
 
     return( ret );
 }
diff --git a/library/md2.c b/library/md2.c
index b88aa40..1c0b3df 100644
--- a/library/md2.c
+++ b/library/md2.c
@@ -34,6 +34,7 @@
 #if defined(MBEDTLS_MD2_C)
 
 #include "mbedtls/md2.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -48,11 +49,6 @@
 
 #if !defined(MBEDTLS_MD2_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 static const unsigned char PI_SUBST[256] =
 {
     0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
@@ -93,7 +89,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_md2_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) );
 }
 
 void mbedtls_md2_clone( mbedtls_md2_context *dst,
diff --git a/library/md4.c b/library/md4.c
index ba704f5..3f8ddff 100644
--- a/library/md4.c
+++ b/library/md4.c
@@ -34,6 +34,7 @@
 #if defined(MBEDTLS_MD4_C)
 
 #include "mbedtls/md4.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -48,11 +49,6 @@
 
 #if !defined(MBEDTLS_MD4_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (little endian)
  */
@@ -86,7 +82,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
 }
 
 void mbedtls_md4_clone( mbedtls_md4_context *dst,
diff --git a/library/md5.c b/library/md5.c
index 8440ebf..8238c2b 100644
--- a/library/md5.c
+++ b/library/md5.c
@@ -33,6 +33,7 @@
 #if defined(MBEDTLS_MD5_C)
 
 #include "mbedtls/md5.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -47,11 +48,6 @@
 
 #if !defined(MBEDTLS_MD5_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (little endian)
  */
@@ -85,7 +81,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) );
 }
 
 void mbedtls_md5_clone( mbedtls_md5_context *dst,
diff --git a/library/memory_buffer_alloc.c b/library/memory_buffer_alloc.c
index 821ae2c..ceaeda1 100644
--- a/library/memory_buffer_alloc.c
+++ b/library/memory_buffer_alloc.c
@@ -31,6 +31,7 @@
 /* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C
    is dependent upon MBEDTLS_PLATFORM_C */
 #include "mbedtls/platform.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -42,11 +43,6 @@
 #include "mbedtls/threading.h"
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 #define MAGIC1       0xFF00AA55
 #define MAGIC2       0xEE119966
 #define MAX_BT 20
@@ -612,7 +608,7 @@
 #if defined(MBEDTLS_THREADING_C)
     mbedtls_mutex_free( &heap.mutex );
 #endif
-    mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) );
+    mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) );
 }
 
 #if defined(MBEDTLS_SELF_TEST)
diff --git a/library/pem.c b/library/pem.c
index 13f9208..6069a23 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -33,6 +33,7 @@
 #include "mbedtls/aes.h"
 #include "mbedtls/md5.h"
 #include "mbedtls/cipher.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -45,11 +46,6 @@
 #endif
 
 #if defined(MBEDTLS_PEM_PARSE_C)
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 void mbedtls_pem_init( mbedtls_pem_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_pem_context ) );
@@ -135,7 +131,7 @@
 
 exit:
     mbedtls_md5_free( &md5_ctx );
-    mbedtls_zeroize( md5sum, 16 );
+    mbedtls_platform_zeroize( md5sum, 16 );
 
     return( ret );
 }
@@ -164,7 +160,7 @@
 
 exit:
     mbedtls_des_free( &des_ctx );
-    mbedtls_zeroize( des_key, 8 );
+    mbedtls_platform_zeroize( des_key, 8 );
 
     return( ret );
 }
@@ -192,7 +188,7 @@
 
 exit:
     mbedtls_des3_free( &des3_ctx );
-    mbedtls_zeroize( des3_key, 24 );
+    mbedtls_platform_zeroize( des3_key, 24 );
 
     return( ret );
 }
@@ -222,7 +218,7 @@
 
 exit:
     mbedtls_aes_free( &aes_ctx );
-    mbedtls_zeroize( aes_key, keylen );
+    mbedtls_platform_zeroize( aes_key, keylen );
 
     return( ret );
 }
@@ -359,7 +355,7 @@
 
     if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 )
     {
-        mbedtls_zeroize( buf, len );
+        mbedtls_platform_zeroize( buf, len );
         mbedtls_free( buf );
         return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
     }
@@ -370,7 +366,7 @@
     ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
         if( pwd == NULL )
         {
-            mbedtls_zeroize( buf, len );
+            mbedtls_platform_zeroize( buf, len );
             mbedtls_free( buf );
             return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED );
         }
@@ -407,12 +403,12 @@
          */
         if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
         {
-            mbedtls_zeroize( buf, len );
+            mbedtls_platform_zeroize( buf, len );
             mbedtls_free( buf );
             return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH );
         }
 #else
-        mbedtls_zeroize( buf, len );
+        mbedtls_platform_zeroize( buf, len );
         mbedtls_free( buf );
         return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
 #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
@@ -428,11 +424,11 @@
 void mbedtls_pem_free( mbedtls_pem_context *ctx )
 {
     if( ctx->buf != NULL )
-        mbedtls_zeroize( ctx->buf, ctx->buflen );
+        mbedtls_platform_zeroize( ctx->buf, ctx->buflen );
     mbedtls_free( ctx->buf );
     mbedtls_free( ctx->info );
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_pem_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) );
 }
 #endif /* MBEDTLS_PEM_PARSE_C */
 
diff --git a/library/pk.c b/library/pk.c
index b52c73f..f05b139 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -29,6 +29,8 @@
 #include "mbedtls/pk.h"
 #include "mbedtls/pk_internal.h"
 
+#include "mbedtls/platform_util.h"
+
 #if defined(MBEDTLS_RSA_C)
 #include "mbedtls/rsa.h"
 #endif
@@ -42,11 +44,6 @@
 #include <limits.h>
 #include <stdint.h>
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * Initialise a mbedtls_pk_context
  */
@@ -69,7 +66,7 @@
 
     ctx->pk_info->ctx_free_func( ctx->pk_ctx );
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
 }
 
 /*
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 5446e23..2c7d2d7 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -41,6 +41,10 @@
 #include "mbedtls/ecdsa.h"
 #endif
 
+#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
+#include "mbedtls/platform_util.h"
+#endif
+
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
@@ -52,13 +56,6 @@
 #include <limits.h>
 #include <stdint.h>
 
-#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-#endif
-
 #if defined(MBEDTLS_RSA_C)
 static int rsa_can_do( mbedtls_pk_type_t type )
 {
@@ -498,7 +495,7 @@
 
 static void rsa_alt_free_wrap( void *ctx )
 {
-    mbedtls_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) );
     mbedtls_free( ctx );
 }
 
diff --git a/library/pkcs12.c b/library/pkcs12.c
index c603a13..16a15cb 100644
--- a/library/pkcs12.c
+++ b/library/pkcs12.c
@@ -36,6 +36,7 @@
 #include "mbedtls/pkcs12.h"
 #include "mbedtls/asn1.h"
 #include "mbedtls/cipher.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -47,11 +48,6 @@
 #include "mbedtls/des.h"
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
                                     mbedtls_asn1_buf *salt, int *iterations )
 {
@@ -166,7 +162,7 @@
         goto exit;
 
 exit:
-    mbedtls_zeroize( key, sizeof( key ) );
+    mbedtls_platform_zeroize( key, sizeof( key ) );
     mbedtls_arc4_free( &ctx );
 
     return( ret );
@@ -223,8 +219,8 @@
         ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;
 
 exit:
-    mbedtls_zeroize( key, sizeof( key ) );
-    mbedtls_zeroize( iv,  sizeof( iv  ) );
+    mbedtls_platform_zeroize( key, sizeof( key ) );
+    mbedtls_platform_zeroize( iv,  sizeof( iv  ) );
     mbedtls_cipher_free( &cipher_ctx );
 
     return( ret );
@@ -352,10 +348,10 @@
     ret = 0;
 
 exit:
-    mbedtls_zeroize( salt_block, sizeof( salt_block ) );
-    mbedtls_zeroize( pwd_block, sizeof( pwd_block ) );
-    mbedtls_zeroize( hash_block, sizeof( hash_block ) );
-    mbedtls_zeroize( hash_output, sizeof( hash_output ) );
+    mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) );
+    mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) );
+    mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) );
+    mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) );
 
     mbedtls_md_free( &md_ctx );
 
diff --git a/library/pkparse.c b/library/pkparse.c
index 5ad5edf..ccb7f54 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -30,6 +30,7 @@
 #include "mbedtls/pk.h"
 #include "mbedtls/asn1.h"
 #include "mbedtls/oid.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -60,14 +61,6 @@
 #define mbedtls_free       free
 #endif
 
-#if defined(MBEDTLS_FS_IO) || \
-    defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-#endif
-
 #if defined(MBEDTLS_FS_IO)
 /*
  * Load all data from a file into a given buffer.
@@ -105,7 +98,7 @@
     {
         fclose( f );
 
-        mbedtls_zeroize( *buf, *n );
+        mbedtls_platform_zeroize( *buf, *n );
         mbedtls_free( *buf );
 
         return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
@@ -140,7 +133,7 @@
         ret = mbedtls_pk_parse_key( ctx, buf, n,
                 (const unsigned char *) pwd, strlen( pwd ) );
 
-    mbedtls_zeroize( buf, n );
+    mbedtls_platform_zeroize( buf, n );
     mbedtls_free( buf );
 
     return( ret );
@@ -160,7 +153,7 @@
 
     ret = mbedtls_pk_parse_public_key( ctx, buf, n );
 
-    mbedtls_zeroize( buf, n );
+    mbedtls_platform_zeroize( buf, n );
     mbedtls_free( buf );
 
     return( ret );
@@ -1295,7 +1288,7 @@
         ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen,
                                                 pwd, pwdlen );
 
-        mbedtls_zeroize( key_copy, keylen );
+        mbedtls_platform_zeroize( key_copy, keylen );
         mbedtls_free( key_copy );
     }
 
diff --git a/library/platform.c b/library/platform.c
index a295f9b..9e99287 100644
--- a/library/platform.c
+++ b/library/platform.c
@@ -28,14 +28,7 @@
 #if defined(MBEDTLS_PLATFORM_C)
 
 #include "mbedtls/platform.h"
-
-#if defined(MBEDTLS_ENTROPY_NV_SEED) && \
-    !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO)
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-#endif
+#include "mbedtls/platform_util.h"
 
 #if defined(MBEDTLS_PLATFORM_MEMORY)
 #if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
@@ -241,7 +234,7 @@
     if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len )
     {
         fclose( file );
-        mbedtls_zeroize( buf, buf_len );
+        mbedtls_platform_zeroize( buf, buf_len );
         return( -1 );
     }
 
diff --git a/library/platform_util.c b/library/platform_util.c
new file mode 100644
index 0000000..1a57de9
--- /dev/null
+++ b/library/platform_util.c
@@ -0,0 +1,67 @@
+/*
+ * Common and shared functions used by multiple modules in the Mbed TLS
+ * library.
+ *
+ *  Copyright (C) 2018, Arm Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include "mbedtls/platform_util.h"
+
+#include <stddef.h>
+#include <string.h>
+
+#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)
+/*
+ * This implementation should never be optimized out by the compiler
+ *
+ * This implementation for mbedtls_platform_zeroize() was inspired from Colin
+ * Percival's blog article at:
+ *
+ * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
+ *
+ * It uses a volatile function pointer to the standard memset(). Because the
+ * pointer is volatile the compiler expects it to change at
+ * any time and will not optimize out the call that could potentially perform
+ * other operations on the input buffer instead of just setting it to 0.
+ * Nevertheless, as pointed out by davidtgoldblatt on Hacker News
+ * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for
+ * details), optimizations of the following form are still possible:
+ *
+ * if( memset_func != memset )
+ *     memset_func( buf, 0, len );
+ *
+ * Note that it is extremely difficult to guarantee that
+ * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers
+ * in a portable way. For this reason, Mbed TLS also provides the configuration
+ * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure
+ * mbedtls_platform_zeroize() to use a suitable implementation for their
+ * platform and needs.
+ */
+static void * (* const volatile memset_func)( void *, int, size_t ) = memset;
+
+void mbedtls_platform_zeroize( void *buf, size_t len )
+{
+    memset_func( buf, 0, len );
+}
+#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
diff --git a/library/ripemd160.c b/library/ripemd160.c
index 2ba48b7..bd25ada 100644
--- a/library/ripemd160.c
+++ b/library/ripemd160.c
@@ -34,6 +34,7 @@
 #if defined(MBEDTLS_RIPEMD160_C)
 
 #include "mbedtls/ripemd160.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -71,11 +72,6 @@
 }
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) );
@@ -86,7 +82,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) );
 }
 
 void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst,
diff --git a/library/rsa.c b/library/rsa.c
index 729e1f7..88c1cf1 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -48,6 +48,7 @@
 #include "mbedtls/rsa.h"
 #include "mbedtls/rsa_internal.h"
 #include "mbedtls/oid.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -70,11 +71,6 @@
 
 #if !defined(MBEDTLS_RSA_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 #if defined(MBEDTLS_PKCS1_V15)
 /* constant-time buffer comparison */
 static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
@@ -1060,7 +1056,7 @@
     }
 
 exit:
-    mbedtls_zeroize( mask, sizeof( mask ) );
+    mbedtls_platform_zeroize( mask, sizeof( mask ) );
 
     return( ret );
 }
@@ -1374,8 +1370,8 @@
     ret = 0;
 
 cleanup:
-    mbedtls_zeroize( buf, sizeof( buf ) );
-    mbedtls_zeroize( lhash, sizeof( lhash ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( lhash, sizeof( lhash ) );
 
     return( ret );
 }
@@ -1472,7 +1468,7 @@
     ret = 0;
 
 cleanup:
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     return( ret );
 }
@@ -1603,7 +1599,7 @@
     p += hlen;
     *p++ = 0xBC;
 
-    mbedtls_zeroize( salt, sizeof( salt ) );
+    mbedtls_platform_zeroize( salt, sizeof( salt ) );
 
 exit:
     mbedtls_md_free( &md_ctx );
@@ -1745,7 +1741,7 @@
      * after the initial bounds check. */
     if( p != dst + dst_len )
     {
-        mbedtls_zeroize( dst, dst_len );
+        mbedtls_platform_zeroize( dst, dst_len );
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
     }
 
@@ -2082,13 +2078,13 @@
 
     if( encoded != NULL )
     {
-        mbedtls_zeroize( encoded, sig_len );
+        mbedtls_platform_zeroize( encoded, sig_len );
         mbedtls_free( encoded );
     }
 
     if( encoded_expected != NULL )
     {
-        mbedtls_zeroize( encoded_expected, sig_len );
+        mbedtls_platform_zeroize( encoded_expected, sig_len );
         mbedtls_free( encoded_expected );
     }
 
diff --git a/library/sha1.c b/library/sha1.c
index 1f29a0f..1587de4 100644
--- a/library/sha1.c
+++ b/library/sha1.c
@@ -33,6 +33,7 @@
 #if defined(MBEDTLS_SHA1_C)
 
 #include "mbedtls/sha1.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -47,11 +48,6 @@
 
 #if !defined(MBEDTLS_SHA1_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -85,7 +81,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
 }
 
 void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
diff --git a/library/sha256.c b/library/sha256.c
index f39bcba..695485d 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -33,6 +33,7 @@
 #if defined(MBEDTLS_SHA256_C)
 
 #include "mbedtls/sha256.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -50,11 +51,6 @@
 
 #if !defined(MBEDTLS_SHA256_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -88,7 +84,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
 }
 
 void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
diff --git a/library/sha512.c b/library/sha512.c
index 97cee07..6de94e9 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -33,6 +33,7 @@
 #if defined(MBEDTLS_SHA512_C)
 
 #include "mbedtls/sha512.h"
+#include "mbedtls/platform_util.h"
 
 #if defined(_MSC_VER) || defined(__WATCOMC__)
   #define UL64(x) x##ui64
@@ -56,11 +57,6 @@
 
 #if !defined(MBEDTLS_SHA512_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 64-bit integer manipulation macros (big endian)
  */
@@ -102,7 +98,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
 }
 
 void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index f4dc02a..b3dc4db 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -48,10 +48,7 @@
 #endif
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
+#include "mbedtls/platform_util.h"
 #endif
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@@ -3342,8 +3339,8 @@
     if( ticket_len == 0 )
         return( 0 );
 
-    mbedtls_zeroize( ssl->session_negotiate->ticket,
-                      ssl->session_negotiate->ticket_len );
+    mbedtls_platform_zeroize( ssl->session_negotiate->ticket,
+                              ssl->session_negotiate->ticket_len );
     mbedtls_free( ssl->session_negotiate->ticket );
     ssl->session_negotiate->ticket = NULL;
     ssl->session_negotiate->ticket_len = 0;
diff --git a/library/ssl_cookie.c b/library/ssl_cookie.c
index caf1199..56e9bdd 100644
--- a/library/ssl_cookie.c
+++ b/library/ssl_cookie.c
@@ -40,14 +40,10 @@
 
 #include "mbedtls/ssl_cookie.h"
 #include "mbedtls/ssl_internal.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is
  * available. Try SHA-256 first, 512 wastes resources since we need to stay
@@ -101,7 +97,7 @@
     mbedtls_mutex_free( &ctx->mutex );
 #endif
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) );
 }
 
 int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
@@ -122,7 +118,7 @@
     if( ret != 0 )
         return( ret );
 
-    mbedtls_zeroize( key, sizeof( key ) );
+    mbedtls_platform_zeroize( key, sizeof( key ) );
 
     return( 0 );
 }
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 2c180f1..09b7a3f 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -38,6 +38,7 @@
 #include "mbedtls/debug.h"
 #include "mbedtls/ssl.h"
 #include "mbedtls/ssl_internal.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -49,13 +50,6 @@
 #include "mbedtls/platform_time.h"
 #endif
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-#endif
-
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
 int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl,
                                  const unsigned char *info,
@@ -553,7 +547,7 @@
     memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) );
 
     /* Zeroize instead of free as we copied the content */
-    mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) );
+    mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) );
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) );
 
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index 4d9116d..a2b3048 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -36,14 +36,10 @@
 #endif
 
 #include "mbedtls/ssl_ticket.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * Initialze context
  */
@@ -83,7 +79,7 @@
                                  mbedtls_cipher_get_key_bitlen( &key->ctx ),
                                  MBEDTLS_ENCRYPT );
 
-    mbedtls_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
     return( ret );
 }
@@ -483,7 +479,7 @@
     mbedtls_mutex_free( &ctx->mutex );
 #endif
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) );
 }
 
 #endif /* MBEDTLS_SSL_TICKET_C */
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 8a903c5..cf1b694 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -46,6 +46,7 @@
 #include "mbedtls/debug.h"
 #include "mbedtls/ssl.h"
 #include "mbedtls/ssl_internal.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -53,11 +54,6 @@
 #include "mbedtls/oid.h"
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /* Length of the "epoch" field in the record header */
 static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl )
 {
@@ -269,8 +265,8 @@
     mbedtls_md5_free(  &md5  );
     mbedtls_sha1_free( &sha1 );
 
-    mbedtls_zeroize( padding, sizeof( padding ) );
-    mbedtls_zeroize( sha1sum, sizeof( sha1sum ) );
+    mbedtls_platform_zeroize( padding, sizeof( padding ) );
+    mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) );
 
     return( ret );
 }
@@ -367,8 +363,8 @@
 
     mbedtls_md_free( &md_ctx );
 
-    mbedtls_zeroize( tmp, sizeof( tmp ) );
-    mbedtls_zeroize( h_i, sizeof( h_i ) );
+    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+    mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
 
     return( 0 );
 }
@@ -432,8 +428,8 @@
 
     mbedtls_md_free( &md_ctx );
 
-    mbedtls_zeroize( tmp, sizeof( tmp ) );
-    mbedtls_zeroize( h_i, sizeof( h_i ) );
+    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+    mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
 
     return( 0 );
 }
@@ -642,7 +638,8 @@
             return( ret );
         }
 
-        mbedtls_zeroize( handshake->premaster, sizeof(handshake->premaster) );
+        mbedtls_platform_zeroize( handshake->premaster,
+                                  sizeof(handshake->premaster) );
     }
     else
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
@@ -653,7 +650,7 @@
     memcpy( tmp, handshake->randbytes, 64 );
     memcpy( handshake->randbytes, tmp + 32, 32 );
     memcpy( handshake->randbytes + 32, tmp, 32 );
-    mbedtls_zeroize( tmp, sizeof( tmp ) );
+    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
 
     /*
      *  SSLv3:
@@ -681,7 +678,8 @@
     MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 );
     MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
 
-    mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) );
+    mbedtls_platform_zeroize( handshake->randbytes,
+                              sizeof( handshake->randbytes ) );
 
     /*
      * Determine the appropriate key, IV and MAC length.
@@ -948,7 +946,7 @@
     }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
-    mbedtls_zeroize( keyblk, sizeof( keyblk ) );
+    mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) );
 
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     // Initialize compression
@@ -5030,9 +5028,9 @@
     mbedtls_md5_free(  &md5  );
     mbedtls_sha1_free( &sha1 );
 
-    mbedtls_zeroize(  padbuf, sizeof(  padbuf ) );
-    mbedtls_zeroize(  md5sum, sizeof(  md5sum ) );
-    mbedtls_zeroize( sha1sum, sizeof( sha1sum ) );
+    mbedtls_platform_zeroize(  padbuf, sizeof(  padbuf ) );
+    mbedtls_platform_zeroize(  md5sum, sizeof(  md5sum ) );
+    mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
@@ -5091,7 +5089,7 @@
     mbedtls_md5_free(  &md5  );
     mbedtls_sha1_free( &sha1 );
 
-    mbedtls_zeroize(  padbuf, sizeof(  padbuf ) );
+    mbedtls_platform_zeroize(  padbuf, sizeof(  padbuf ) );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
@@ -5141,7 +5139,7 @@
 
     mbedtls_sha256_free( &sha256 );
 
-    mbedtls_zeroize(  padbuf, sizeof(  padbuf ) );
+    mbedtls_platform_zeroize(  padbuf, sizeof(  padbuf ) );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
@@ -5190,7 +5188,7 @@
 
     mbedtls_sha512_free( &sha512 );
 
-    mbedtls_zeroize(  padbuf, sizeof( padbuf ) );
+    mbedtls_platform_zeroize(  padbuf, sizeof( padbuf ) );
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
@@ -6109,7 +6107,7 @@
 
     if( conf->psk != NULL )
     {
-        mbedtls_zeroize( conf->psk, conf->psk_len );
+        mbedtls_platform_zeroize( conf->psk, conf->psk_len );
 
         mbedtls_free( conf->psk );
         conf->psk = NULL;
@@ -6152,7 +6150,8 @@
 
     if( ssl->handshake->psk != NULL )
     {
-        mbedtls_zeroize( ssl->handshake->psk, ssl->handshake->psk_len );
+        mbedtls_platform_zeroize( ssl->handshake->psk,
+                                  ssl->handshake->psk_len );
         mbedtls_free( ssl->handshake->psk );
         ssl->handshake->psk_len = 0;
     }
@@ -6282,7 +6281,7 @@
 
     if( ssl->hostname != NULL )
     {
-        mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) );
+        mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) );
         mbedtls_free( ssl->hostname );
     }
 
@@ -7395,7 +7394,7 @@
     mbedtls_md_free( &transform->md_ctx_enc );
     mbedtls_md_free( &transform->md_ctx_dec );
 
-    mbedtls_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
+    mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
 }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -7455,7 +7454,7 @@
 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
     if( handshake->psk != NULL )
     {
-        mbedtls_zeroize( handshake->psk, handshake->psk_len );
+        mbedtls_platform_zeroize( handshake->psk, handshake->psk_len );
         mbedtls_free( handshake->psk );
     }
 #endif
@@ -7485,7 +7484,8 @@
     ssl_flight_free( handshake->flight );
 #endif
 
-    mbedtls_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) );
+    mbedtls_platform_zeroize( handshake,
+                              sizeof( mbedtls_ssl_handshake_params ) );
 }
 
 void mbedtls_ssl_session_free( mbedtls_ssl_session *session )
@@ -7505,7 +7505,7 @@
     mbedtls_free( session->ticket );
 #endif
 
-    mbedtls_zeroize( session, sizeof( mbedtls_ssl_session ) );
+    mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) );
 }
 
 /*
@@ -7520,20 +7520,20 @@
 
     if( ssl->out_buf != NULL )
     {
-        mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN );
+        mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN );
         mbedtls_free( ssl->out_buf );
     }
 
     if( ssl->in_buf != NULL )
     {
-        mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN );
+        mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN );
         mbedtls_free( ssl->in_buf );
     }
 
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     if( ssl->compress_buf != NULL )
     {
-        mbedtls_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN );
+        mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN );
         mbedtls_free( ssl->compress_buf );
     }
 #endif
@@ -7564,7 +7564,7 @@
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     if( ssl->hostname != NULL )
     {
-        mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) );
+        mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) );
         mbedtls_free( ssl->hostname );
     }
 #endif
@@ -7584,7 +7584,7 @@
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) );
 
     /* Actually clear after last debug message */
-    mbedtls_zeroize( ssl, sizeof( mbedtls_ssl_context ) );
+    mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) );
 }
 
 /*
@@ -7811,7 +7811,7 @@
 #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
     if( conf->psk != NULL )
     {
-        mbedtls_zeroize( conf->psk, conf->psk_len );
+        mbedtls_platform_zeroize( conf->psk, conf->psk_len );
         mbedtls_free( conf->psk );
         conf->psk = NULL;
         conf->psk_len = 0;
@@ -7819,7 +7819,7 @@
 
     if( conf->psk_identity != NULL )
     {
-        mbedtls_zeroize( conf->psk_identity, conf->psk_identity_len );
+        mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len );
         mbedtls_free( conf->psk_identity );
         conf->psk_identity = NULL;
         conf->psk_identity_len = 0;
@@ -7830,7 +7830,7 @@
     ssl_key_cert_free( conf->key_cert );
 #endif
 
-    mbedtls_zeroize( conf, sizeof( mbedtls_ssl_config ) );
+    mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) );
 }
 
 #if defined(MBEDTLS_PK_C) && \
diff --git a/library/x509_crl.c b/library/x509_crl.c
index b0f39d4..8450f87 100644
--- a/library/x509_crl.c
+++ b/library/x509_crl.c
@@ -39,6 +39,7 @@
 
 #include "mbedtls/x509_crl.h"
 #include "mbedtls/oid.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -66,11 +67,6 @@
 #include <stdio.h>
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  *  Version  ::=  INTEGER  {  v1(0), v2(1)  }
  */
@@ -616,7 +612,7 @@
 
     ret = mbedtls_x509_crl_parse( chain, buf, n );
 
-    mbedtls_zeroize( buf, n );
+    mbedtls_platform_zeroize( buf, n );
     mbedtls_free( buf );
 
     return( ret );
@@ -737,7 +733,7 @@
         {
             name_prv = name_cur;
             name_cur = name_cur->next;
-            mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
+            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
             mbedtls_free( name_prv );
         }
 
@@ -746,13 +742,14 @@
         {
             entry_prv = entry_cur;
             entry_cur = entry_cur->next;
-            mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) );
+            mbedtls_platform_zeroize( entry_prv,
+                                      sizeof( mbedtls_x509_crl_entry ) );
             mbedtls_free( entry_prv );
         }
 
         if( crl_cur->raw.p != NULL )
         {
-            mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len );
+            mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len );
             mbedtls_free( crl_cur->raw.p );
         }
 
@@ -766,7 +763,7 @@
         crl_prv = crl_cur;
         crl_cur = crl_cur->next;
 
-        mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) );
+        mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) );
         if( crl_prv != crl )
             mbedtls_free( crl_prv );
     }
diff --git a/library/x509_crt.c b/library/x509_crt.c
index afff4e1..462cbcf 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -41,6 +41,7 @@
 
 #include "mbedtls/x509_crt.h"
 #include "mbedtls/oid.h"
+#include "mbedtls/platform_util.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -90,11 +91,6 @@
  */
 #define X509_MAX_VERIFY_CHAIN_SIZE    ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * Default profile
  */
@@ -1115,7 +1111,7 @@
 
     ret = mbedtls_x509_crt_parse( chain, buf, n );
 
-    mbedtls_zeroize( buf, n );
+    mbedtls_platform_zeroize( buf, n );
     mbedtls_free( buf );
 
     return( ret );
@@ -2426,7 +2422,7 @@
         {
             name_prv = name_cur;
             name_cur = name_cur->next;
-            mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
+            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
             mbedtls_free( name_prv );
         }
 
@@ -2435,7 +2431,7 @@
         {
             name_prv = name_cur;
             name_cur = name_cur->next;
-            mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
+            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
             mbedtls_free( name_prv );
         }
 
@@ -2444,7 +2440,8 @@
         {
             seq_prv = seq_cur;
             seq_cur = seq_cur->next;
-            mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) );
+            mbedtls_platform_zeroize( seq_prv,
+                                      sizeof( mbedtls_x509_sequence ) );
             mbedtls_free( seq_prv );
         }
 
@@ -2453,13 +2450,14 @@
         {
             seq_prv = seq_cur;
             seq_cur = seq_cur->next;
-            mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) );
+            mbedtls_platform_zeroize( seq_prv,
+                                      sizeof( mbedtls_x509_sequence ) );
             mbedtls_free( seq_prv );
         }
 
         if( cert_cur->raw.p != NULL )
         {
-            mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len );
+            mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
             mbedtls_free( cert_cur->raw.p );
         }
 
@@ -2473,7 +2471,7 @@
         cert_prv = cert_cur;
         cert_cur = cert_cur->next;
 
-        mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
+        mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
         if( cert_prv != crt )
             mbedtls_free( cert_prv );
     }
diff --git a/library/x509_csr.c b/library/x509_csr.c
index 26a06db..3e8e8fb 100644
--- a/library/x509_csr.c
+++ b/library/x509_csr.c
@@ -39,6 +39,7 @@
 
 #include "mbedtls/x509_csr.h"
 #include "mbedtls/oid.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -60,11 +61,6 @@
 #include <stdio.h>
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  *  Version  ::=  INTEGER  {  v1(0)  }
  */
@@ -325,7 +321,7 @@
 
     ret = mbedtls_x509_csr_parse( csr, buf, n );
 
-    mbedtls_zeroize( buf, n );
+    mbedtls_platform_zeroize( buf, n );
     mbedtls_free( buf );
 
     return( ret );
@@ -407,17 +403,17 @@
     {
         name_prv = name_cur;
         name_cur = name_cur->next;
-        mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
+        mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
         mbedtls_free( name_prv );
     }
 
     if( csr->raw.p != NULL )
     {
-        mbedtls_zeroize( csr->raw.p, csr->raw.len );
+        mbedtls_platform_zeroize( csr->raw.p, csr->raw.len );
         mbedtls_free( csr->raw.p );
     }
 
-    mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) );
+    mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) );
 }
 
 #endif /* MBEDTLS_X509_CSR_PARSE_C */
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 41dfe87..b1ef216 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -37,6 +37,7 @@
 #include "mbedtls/oid.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/sha1.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -44,11 +45,6 @@
 #include "mbedtls/pem.h"
 #endif /* MBEDTLS_PEM_WRITE_C */
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
@@ -65,7 +61,7 @@
     mbedtls_asn1_free_named_data_list( &ctx->issuer );
     mbedtls_asn1_free_named_data_list( &ctx->extensions );
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
 }
 
 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version )
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
index e800538..66cee56 100644
--- a/library/x509write_csr.c
+++ b/library/x509write_csr.c
@@ -35,6 +35,7 @@
 #include "mbedtls/x509_csr.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/asn1write.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -43,11 +44,6 @@
 #include "mbedtls/pem.h"
 #endif
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
@@ -58,7 +54,7 @@
     mbedtls_asn1_free_named_data_list( &ctx->subject );
     mbedtls_asn1_free_named_data_list( &ctx->extensions );
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_csr ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) );
 }
 
 void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg )
diff --git a/library/xtea.c b/library/xtea.c
index fe0a350..a33707b 100644
--- a/library/xtea.c
+++ b/library/xtea.c
@@ -28,6 +28,7 @@
 #if defined(MBEDTLS_XTEA_C)
 
 #include "mbedtls/xtea.h"
+#include "mbedtls/platform_util.h"
 
 #include <string.h>
 
@@ -42,11 +43,6 @@
 
 #if !defined(MBEDTLS_XTEA_ALT)
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /*
  * 32-bit integer manipulation macros (big endian)
  */
@@ -80,7 +76,7 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_xtea_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_xtea_context ) );
 }
 
 /*
diff --git a/programs/.gitignore b/programs/.gitignore
index 27055b8..ddfa1a4 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -47,6 +47,7 @@
 test/selftest
 test/ssl_cert_test
 test/udp_proxy
+test/zeroize
 util/pem2der
 util/strerror
 x509/cert_app
diff --git a/programs/Makefile b/programs/Makefile
index 25f184f..080e82d 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -67,6 +67,7 @@
 	random/gen_random_ctr_drbg$(EXEXT)				\
 	test/ssl_cert_test$(EXEXT)	test/benchmark$(EXEXT)		\
 	test/selftest$(EXEXT)		test/udp_proxy$(EXEXT)		\
+	test/zeroize$(EXEXT)						\
 	util/pem2der$(EXEXT)		util/strerror$(EXEXT)		\
 	x509/cert_app$(EXEXT)		x509/crl_app$(EXEXT)		\
 	x509/cert_req$(EXEXT)		x509/cert_write$(EXEXT)		\
@@ -249,6 +250,10 @@
 	echo "  CC    test/udp_proxy.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/udp_proxy.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test/zeroize$(EXEXT): test/zeroize.c $(DEP)
+	echo "  CC    test/zeroize.c"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/zeroize.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 util/pem2der$(EXEXT): util/pem2der.c $(DEP)
 	echo "  CC    util/pem2der.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) util/pem2der.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index 0ed7145..0c5ce27 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -22,6 +22,9 @@
 add_executable(udp_proxy udp_proxy.c)
 target_link_libraries(udp_proxy ${libs})
 
+add_executable(zeroize zeroize.c)
+target_link_libraries(zeroize ${libs})
+
 install(TARGETS selftest benchmark ssl_cert_test udp_proxy
         DESTINATION "bin"
         PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/programs/test/zeroize.c b/programs/test/zeroize.c
new file mode 100644
index 0000000..252438b
--- /dev/null
+++ b/programs/test/zeroize.c
@@ -0,0 +1,101 @@
+/*
+ * Zeroize application for debugger-driven testing
+ *
+ * This is a simple test application used for debugger-driven testing to check
+ * whether calls to mbedtls_platform_zeroize() are being eliminated by compiler
+ * optimizations. This application is used by the GDB script at
+ * tests/scripts/test_zeroize.gdb under the assumption that the code does not
+ * change often (as opposed to the library code) because the script sets a
+ * breakpoint at the last return statement in the main() function of this
+ * program. The debugger facilities are then used to manually inspect the
+ * memory and verify that the call to mbedtls_platform_zeroize() was not
+ * eliminated.
+ *
+ *  Copyright (C) 2018, Arm Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stdio.h>
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_printf     printf
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif
+
+#include "mbedtls/platform_util.h"
+
+#define BUFFER_LEN 1024
+
+void usage( void )
+{
+    mbedtls_printf( "Zeroize is a simple program to assist with testing\n" );
+    mbedtls_printf( "the mbedtls_platform_zeroize() function by using the\n" );
+    mbedtls_printf( "debugger. This program takes a file as input and\n" );
+    mbedtls_printf( "prints the first %d characters. Usage:\n\n", BUFFER_LEN );
+    mbedtls_printf( "       zeroize <FILE>\n" );
+}
+
+int main( int argc, char** argv )
+{
+    int exit_code = MBEDTLS_EXIT_FAILURE;
+    FILE *fp;
+    char buf[BUFFER_LEN];
+    char *p = buf;
+    char *end = p + BUFFER_LEN;
+    char c;
+
+    if( argc != 2 )
+    {
+        mbedtls_printf( "This program takes exactly 1 agument\n" );
+        usage();
+        return( exit_code );
+    }
+
+    fp = fopen( argv[1], "r" );
+    if( fp == NULL )
+    {
+        mbedtls_printf( "Could not open file '%s'\n", argv[1] );
+        return( exit_code );
+    }
+
+    while( ( c = fgetc( fp ) ) != EOF && p < end - 1 )
+        *p++ = c;
+    *p = '\0';
+
+    if( p - buf != 0 )
+    {
+        mbedtls_printf( "%s\n", buf );
+        exit_code = MBEDTLS_EXIT_SUCCESS;
+    }
+    else
+        mbedtls_printf( "The file is empty!\n" );
+
+    fclose( fp );
+    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+
+    return( exit_code );
+}
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 8a43553..e6c7549 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -376,7 +376,7 @@
 # Make sure the tools we need are available.
 check_tools "$OPENSSL" "$OPENSSL_LEGACY" "$GNUTLS_CLI" "$GNUTLS_SERV" \
             "$GNUTLS_LEGACY_CLI" "$GNUTLS_LEGACY_SERV" "doxygen" "dot" \
-            "arm-none-eabi-gcc" "i686-w64-mingw32-gcc"
+            "arm-none-eabi-gcc" "i686-w64-mingw32-gcc" "gdb"
 if [ $RUN_ARMCC -ne 0 ]; then
     check_tools "$ARMC5_CC" "$ARMC5_AR" "$ARMC6_CC" "$ARMC6_AR"
 fi
@@ -862,6 +862,15 @@
 cd "$MBEDTLS_ROOT_DIR"
 rm -rf "$OUT_OF_SOURCE_DIR"
 
+for optimization_flag in -O2 -O3 -Ofast -Os; do
+    for compiler in clang gcc; do
+        msg "test: $compiler $optimization_flag, mbedtls_platform_zeroize()"
+        cleanup
+        CC="$compiler" DEBUG=1 CFLAGS="$optimization_flag" make programs
+        gdb -x tests/scripts/test_zeroize.gdb -nw -batch -nx
+    done
+done
+
 
 
 ################################################################
diff --git a/tests/scripts/test_zeroize.gdb b/tests/scripts/test_zeroize.gdb
new file mode 100644
index 0000000..617ab55
--- /dev/null
+++ b/tests/scripts/test_zeroize.gdb
@@ -0,0 +1,70 @@
+# test_zeroize.gdb
+#
+# This file is part of Mbed TLS (https://tls.mbed.org)
+#
+# Copyright (c) 2018, Arm Limited, All Rights Reserved
+#
+# Purpose
+#
+# Run a test using the debugger to check that the mbedtls_platform_zeroize()
+# function in platform_util.h is not being optimized out by the compiler. To do
+# so, the script loads the test program at programs/test/zeroize.c and sets a
+# breakpoint at the last return statement in main(). When the breakpoint is
+# hit, the debugger manually checks the contents to be zeroized and checks that
+# it is actually cleared.
+#
+# The mbedtls_platform_zeroize() test is debugger driven because there does not
+# seem to be a mechanism to reliably check whether the zeroize calls are being
+# eliminated by compiler optimizations from within the compiled program. The
+# problem is that a compiler would typically remove what it considers to be
+# "unecessary" assignments as part of redundant code elimination. To identify
+# such code, the compilar will create some form dependency graph between
+# reads and writes to variables (among other situations). It will then use this
+# data structure to remove redundant code that does not have an impact on the
+# program's observable behavior. In the case of mbedtls_platform_zeroize(), an
+# intelligent compiler could determine that this function clears a block of
+# memory that is not accessed later in the program, so removing the call to
+# mbedtls_platform_zeroize() does not have an observable behavior. However,
+# inserting a test after a call to mbedtls_platform_zeroize() to check whether
+# the block of memory was correctly zeroed would force the compiler to not
+# eliminate the mbedtls_platform_zeroize() call. If this does not occur, then
+# the compiler potentially has a bug.
+#
+# Note: This test requires that the test program is compiled with -g3.
+#
+# WARNING: There does not seem to be a mechanism in GDB scripts to set a
+# breakpoint at the end of a function (probably because there are a lot of
+# complications as function can have multiple exit points, etc). Therefore, it
+# was necessary to hard-code the line number of the breakpoint in the zeroize.c
+# test app. The assumption is that zeroize.c is a simple test app that does not
+# change often (as opposed to the actual library code), so the breakpoint line
+# number does not need to be updated often.
+
+set confirm off
+file ./programs/test/zeroize
+break zeroize.c:100
+
+set args ./programs/test/zeroize.c
+run
+
+set $i = 0
+set $len = sizeof(buf)
+set $buf = buf
+
+while $i < $len
+    if $buf[$i++] != 0
+        echo The buffer at was not zeroized\n
+        quit 1
+    end
+end
+
+echo The buffer was correctly zeroized\n
+
+continue
+
+if $_exitcode != 0
+    echo The program did not terminate correctly\n
+    quit 1
+end
+
+quit 0
diff --git a/visualc/VS2010/mbedTLS.sln b/visualc/VS2010/mbedTLS.sln
index 686091c..66b96c3 100644
--- a/visualc/VS2010/mbedTLS.sln
+++ b/visualc/VS2010/mbedTLS.sln
@@ -203,6 +203,11 @@
 		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

 	EndProjectSection

 EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zeroize", "zeroize.vcxproj", "{10C01E94-4926-063E-9F56-C84ED190D349}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pem2der", "pem2der.vcxproj", "{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}"

 	ProjectSection(ProjectDependencies) = postProject

 		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

@@ -574,6 +579,14 @@
 		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.Build.0 = Release|Win32

 		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.ActiveCfg = Release|x64

 		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.Build.0 = Release|x64

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.ActiveCfg = Debug|Win32

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.Build.0 = Debug|Win32

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.ActiveCfg = Debug|x64

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.Build.0 = Debug|x64

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|Win32.ActiveCfg = Release|Win32

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|Win32.Build.0 = Release|Win32

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|x64.ActiveCfg = Release|x64

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|x64.Build.0 = Release|x64

 		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|Win32.ActiveCfg = Debug|Win32

 		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|Win32.Build.0 = Debug|Win32

 		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|x64.ActiveCfg = Debug|x64

diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index f13f83c..802cce7 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -197,6 +197,7 @@
     <ClInclude Include="..\..\include\mbedtls\pkcs5.h" />

     <ClInclude Include="..\..\include\mbedtls\platform.h" />

     <ClInclude Include="..\..\include\mbedtls\platform_time.h" />

+    <ClInclude Include="..\..\include\mbedtls\platform_util.h" />

     <ClInclude Include="..\..\include\mbedtls\ripemd160.h" />

     <ClInclude Include="..\..\include\mbedtls\rsa.h" />

     <ClInclude Include="..\..\include\mbedtls\rsa_internal.h" />

@@ -266,6 +267,7 @@
     <ClCompile Include="..\..\library\pkparse.c" />

     <ClCompile Include="..\..\library\pkwrite.c" />

     <ClCompile Include="..\..\library\platform.c" />

+    <ClCompile Include="..\..\library\platform_util.c" />

     <ClCompile Include="..\..\library\ripemd160.c" />

     <ClCompile Include="..\..\library\rsa.c" />

     <ClCompile Include="..\..\library\rsa_internal.c" />

diff --git a/visualc/VS2010/zeroize.vcxproj b/visualc/VS2010/zeroize.vcxproj
new file mode 100644
index 0000000..9d311c7
--- /dev/null
+++ b/visualc/VS2010/zeroize.vcxproj
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\test\zeroize.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">
+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{10C01E94-4926-063E-9F56-C84ED190D349}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>zeroize</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>Windows7.1SDK</PlatformToolset>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <ShowProgress>NotSet</ShowProgress>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <ShowProgress>NotSet</ShowProgress>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <PrecompiledHeader>

+      </PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>