Merge remote-tracking branch 'upstream-public/pr/1593' into evaluation-2
diff --git a/ChangeLog b/ChangeLog
index aff915e..25f3b32 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,35 +2,65 @@
 
 = mbed TLS x.x.x branch released xxxx-xx-xx
 
-Security
-   * Fix a bug in the X.509 module potentially leading to a buffer overread
-     during CRT verification or to invalid or omitted checks for certificate
-     validity. The former can be triggered remotely, while the latter requires
-     a non DER-compliant certificate correctly signed by a trusted CA, or a
-     trusted CA with a non DER-compliant certificate. Found by luocm on GitHub.
-     Fixes #825.
+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.
 
 Features
-   * Add option MBEDTLS_AES_FEWER_TABLES to dynamically compute 3/4 of the AES tables
-     during runtime, thereby reducing the RAM/ROM footprint by ~6kb. Suggested
-     and contributed by jkivilin in #394.
-   * Add initial support for Curve448 (RFC 7748). Only mbedtls_ecp_mul() and
-     ECDH primitive functions (mbedtls_ecdh_gen_public(),
-     mbedtls_ecdh_compute_shared()) are supported for now. Contributed by
-     Nicholas Wilson (#348).
+   * Implement HKDF per RFC 5869. Contributed by Thomas Fossati.
    * Add additional block mode, OFB (Output Feedback), to the AES module and
      cipher abstraction module.
 
+= mbed TLS 2.9.0 branch released 2018-04-30
+
+Security
+   * Fix an issue in the X.509 module which could lead to a buffer overread
+     during certificate validation. Additionally, the issue could also lead to
+     unnecessary callback checks being made or to some validation checks to be
+     omitted. The overread could be triggered remotely, while the other issues
+     would require a non DER-compliant certificate to be correctly signed by a
+     trusted CA, or a trusted CA with a non DER-compliant certificate. Found by
+     luocm. Fixes #825.
+   * Fix the buffer length assertion in the ssl_parse_certificate_request()
+     function which led to an arbitrary overread of the message buffer. The
+     overreads could be caused by receiving a malformed message at the point
+     where an optional signature algorithms list is expected when the signature
+     algorithms section is too short. In builds with debug output, the overread
+     data is output with the debug data.
+   * Fix a client-side bug in the validation of the server's ciphersuite choice
+     which could potentially lead to the client accepting a ciphersuite it didn't
+     offer or a ciphersuite that cannot be used with the TLS or DTLS version
+     chosen by the server. This could lead to corruption of internal data
+     structures for some configurations.
+
+Features
+   * Add an option, MBEDTLS_AES_FEWER_TABLES, to dynamically compute smaller AES
+     tables during runtime, thereby reducing the RAM/ROM footprint by ~6KiB.
+     Suggested and contributed by jkivilin in pull request #394.
+   * Add initial support for Curve448 (RFC 7748). Only mbedtls_ecp_mul() and
+     ECDH primitive functions (mbedtls_ecdh_gen_public(),
+     mbedtls_ecdh_compute_shared()) are supported for now. Contributed by
+     Nicholas Wilson in pull request #348.
+
 API Changes
-   * Add function mbedtls_net_poll to public API allowing to wait for a
-     network context to become ready for reading or writing.
-   * Add function mbedtls_ssl_check_pending to public API allowing to check
-     if more data is pending to be processed in the internal message buffers.
+   * Extend the public API with the function of mbedtls_net_poll() to allow user
+     applications to wait for a network context to become ready before reading
+     or writing.
+   * Add function mbedtls_ssl_check_pending() to the public API to allow
+     a check for whether more more data is pending to be processed in the
+     internal message buffers.
      This function is necessary to determine when it is safe to idle on the
      underlying transport in case event-driven IO is used.
 
 Bugfix
-   * Fix spurious uninitialized variable warning in cmac.c. Fix independently
+   * Fix a spurious uninitialized variable warning in cmac.c. Fix independently
      contributed by Brian J Murray and David Brown.
    * Add missing dependencies in test suites that led to build failures
      in configurations that omit certain hashes or public-key algorithms.
@@ -38,15 +68,16 @@
    * Fix C89 incompatibility in benchmark.c. Contributed by Brendan Shanks.
      #1353
    * Add missing dependencies for MBEDTLS_HAVE_TIME_DATE and
-     MBEDTLS_VERSION_FEATURES in test suites. Contributed by Deomid Ryabkov.
-     Fixes #1299, #1475.
-   * Fix dynamic library building process with Makefile on Mac OS X. Fixed by
-     mnacamura.
+     MBEDTLS_VERSION_FEATURES in some test suites. Contributed by
+     Deomid Ryabkov. Fixes #1299, #1475.
+   * Fix the Makefile build process for building shared libraries on Mac OS X.
+     Fixed by mnacamura.
    * Fix parsing of PKCS#8 encoded Elliptic Curve keys. Previously Mbed TLS was
-     unable to parse keys with only the optional parameters field of the
+     unable to parse keys which had only the optional parameters field of the
      ECPrivateKey structure. Found by Jethro Beekman, fixed in #1379.
-   * Return plaintext data sooner on unpadded CBC decryption, as stated in
-     the mbedtls_cipher_update() documentation. Contributed by Andy Leiserson.
+   * Return the plaintext data more quickly on unpadded CBC decryption, as
+     stated in the mbedtls_cipher_update() documentation. Contributed by
+     Andy Leiserson.
    * Fix overriding and ignoring return values when parsing and writing to
      a file in pk_sign program. Found by kevlut in #1142.
    * Restrict usage of error code MBEDTLS_ERR_SSL_WANT_READ to situations
@@ -54,26 +85,32 @@
      to make progress. Previously, this error code was also occasionally
      returned when unexpected messages were being discarded, ignoring that
      further messages could potentially already be pending to be processed
-     in the internal buffers; these cases lead to deadlocks in case
-     event-driven I/O was used.
-     Found and reported by Hubert Mis in #772.
+     in the internal buffers; these cases led to deadlocks when event-driven
+     I/O was used. Found and reported by Hubert Mis in #772.
+   * Fix buffer length assertions in the ssl_parse_certificate_request()
+     function which leads to a potential one byte overread of the message
+     buffer.
    * Fix invalid buffer sizes passed to zlib during record compression and
      decompression.
+   * Fix the soversion of libmbedcrypto to match the soversion of the
+     maintained 2.7 branch. The soversion was increased in Mbed TLS
+     version 2.7.1 to reflect breaking changes in that release, but the
+     increment was missed in 2.8.0 and later releases outside of the 2.7 branch.
 
 Changes
    * Remove some redundant code in bignum.c. Contributed by Alexey Skalozub.
-   * Support cmake build where Mbed TLS is a subproject. Fix
-     contributed independently by Matthieu Volat and Arne Schwabe.
+   * Support cmake builds where Mbed TLS is a subproject. Fix contributed
+     independently by Matthieu Volat and Arne Schwabe.
    * Improve testing in configurations that omit certain hashes or
      public-key algorithms. Includes contributions by Gert van Dijk.
    * Improve negative testing of X.509 parsing.
    * Do not define global mutexes around readdir() and gmtime() in
      configurations where the feature is disabled. Found and fixed by Gergely
      Budai.
-   * Harden mbedtls_ssl_config_free() against misuse, so that it doesn't
-     leak memory in case the user doesn't use mbedtls_ssl_conf_psk() and
-     instead incorrectly manipulates conf->psk and/or conf->psk_identity
-     directly. Found and fix submitted by junyeonLEE in #1220.
+   * Harden the function mbedtls_ssl_config_free() against misuse, so that it
+     doesn't leak memory if the user doesn't use mbedtls_ssl_conf_psk() and
+     instead incorrectly manipulates the configuration structure directly.
+     Found and fix submitted by junyeonLEE in #1220.
    * Provide an empty implementation of mbedtls_pkcs5_pbes2() when
      MBEDTLS_ASN1_PARSE_C is not enabled. This allows the use of PBKDF2
      without PBES2. Fixed by Marcos Del Sol Vives.
@@ -84,7 +121,7 @@
      Krylov.
    * Improve the documentation of mbedtls_ssl_write(). Suggested by
      Paul Sokolovsky in #1356.
-   * Add an option in the makefile to support ar utilities where the operation
+   * Add an option in the Makefile to support ar utilities where the operation
      letter must not be prefixed by '-', such as LLVM. Found and fixed by
      Alex Hixon.
    * Allow configuring the shared library extension by setting the DLEXT
@@ -97,8 +134,13 @@
    * Improve robustness of mbedtls_ssl_derive_keys against the use of
      HMAC functions with non-HMAC ciphersuites. Independently contributed
      by Jiayuan Chen in #1377. Fixes #1437.
-   * Improve security of RSA key generation by including criteria from FIPS
-     186-4. Contributed by Jethro Beekman. #1380
+   * Improve security of RSA key generation by including criteria from
+     FIPS 186-4. Contributed by Jethro Beekman. #1380
+   * Declare functions in header files even when an alternative implementation
+     of the corresponding module is activated by defining the corresponding
+     MBEDTLS_XXX_ALT macro. This means that alternative implementations do
+     not need to copy the declarations, and ensures that they will have the
+     same API.
    * Add platform setup and teardown calls in test suites.
 
 = mbed TLS 2.8.0 branch released 2018-03-16
@@ -297,7 +339,7 @@
    * Fix ssl_parse_record_header() to silently discard invalid DTLS records
      as recommended in RFC 6347 Section 4.1.2.7.
    * Fix memory leak in mbedtls_ssl_set_hostname() when called multiple times.
-     Found by projectgus and jethrogb, #836.
+     Found by projectgus and Jethro Beekman, #836.
    * Fix usage help in ssl_server2 example. Found and fixed by Bei Lin.
    * Parse signature algorithm extension when renegotiating. Previously,
      renegotiated handshakes would only accept signatures using SHA-1
@@ -491,8 +533,7 @@
      Previous behaviour was to keep processing data even after the alert has
      been sent.
    * Accept empty trusted CA chain in authentication mode
-     MBEDTLS_SSL_VERIFY_OPTIONAL.
-     Found by jethrogb. #864
+     MBEDTLS_SSL_VERIFY_OPTIONAL. Found by Jethro Beekman. #864
    * Fix implementation of mbedtls_ssl_parse_certificate() to not annihilate
      fatal errors in authentication mode MBEDTLS_SSL_VERIFY_OPTIONAL and to
      reflect bad EC curves within verification result.
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index 7952cbc..e27c221 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -24,7 +24,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.8.0 source code documentation
+ * @mainpage mbed TLS v2.9.0 source code documentation
  *
  * This documentation describes the internal structure of mbed TLS.  It was
  * automatically generated from specially formatted comment blocks in
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index ec7a46a..510fa85 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -28,7 +28,7 @@
 # identify the project. Note that if you do not use Doxywizard you need
 # to put quotes around the project name if it contains spaces.
 
-PROJECT_NAME           = "mbed TLS v2.8.0"
+PROJECT_NAME           = "mbed TLS v2.9.0"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index da22722..7632ac0 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -62,14 +62,14 @@
 #define inline __inline
 #endif
 
-#if !defined(MBEDTLS_AES_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_AES_ALT)
+// Regular implementation
+//
+
 /**
  * \brief The AES context-type definition.
  */
@@ -88,6 +88,10 @@
 }
 mbedtls_aes_context;
 
+#else  /* MBEDTLS_AES_ALT */
+#include "aes_alt.h"
+#endif /* MBEDTLS_AES_ALT */
+
 /**
  * \brief          This function initializes the specified AES context.
  *
@@ -436,18 +440,6 @@
 #undef MBEDTLS_DEPRECATED
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_AES_ALT */
-#include "aes_alt.h"
-#endif /* MBEDTLS_AES_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Checkup routine.
  *
diff --git a/include/mbedtls/arc4.h b/include/mbedtls/arc4.h
index f9d93f8..f11fc5b 100644
--- a/include/mbedtls/arc4.h
+++ b/include/mbedtls/arc4.h
@@ -38,14 +38,14 @@
 
 #define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED                  -0x0019  /**< ARC4 hardware accelerator failed. */
 
-#if !defined(MBEDTLS_ARC4_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_ARC4_ALT)
+// Regular implementation
+//
+
 /**
  * \brief     ARC4 context structure
  *
@@ -61,6 +61,10 @@
 }
 mbedtls_arc4_context;
 
+#else  /* MBEDTLS_ARC4_ALT */
+#include "arc4_alt.h"
+#endif /* MBEDTLS_ARC4_ALT */
+
 /**
  * \brief          Initialize ARC4 context
  *
@@ -118,18 +122,6 @@
 int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
                 unsigned char *output );
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_ARC4_ALT */
-#include "arc4_alt.h"
-#endif /* MBEDTLS_ARC4_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Checkup routine
  *
diff --git a/include/mbedtls/blowfish.h b/include/mbedtls/blowfish.h
index c0ef5a0..22479be 100644
--- a/include/mbedtls/blowfish.h
+++ b/include/mbedtls/blowfish.h
@@ -44,14 +44,14 @@
 #define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED                   -0x0017  /**< Blowfish hardware accelerator failed. */
 #define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH              -0x0018  /**< Invalid data input length. */
 
-#if !defined(MBEDTLS_BLOWFISH_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_BLOWFISH_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          Blowfish context structure
  */
@@ -62,6 +62,10 @@
 }
 mbedtls_blowfish_context;
 
+#else  /* MBEDTLS_BLOWFISH_ALT */
+#include "blowfish_alt.h"
+#endif /* MBEDTLS_BLOWFISH_ALT */
+
 /**
  * \brief          Initialize Blowfish context
  *
@@ -198,8 +202,4 @@
 }
 #endif
 
-#else  /* MBEDTLS_BLOWFISH_ALT */
-#include "blowfish_alt.h"
-#endif /* MBEDTLS_BLOWFISH_ALT */
-
 #endif /* blowfish.h */
diff --git a/include/mbedtls/camellia.h b/include/mbedtls/camellia.h
index cf07629..f0466bf 100644
--- a/include/mbedtls/camellia.h
+++ b/include/mbedtls/camellia.h
@@ -40,14 +40,14 @@
 #define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH         -0x0026  /**< Invalid data input length. */
 #define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED              -0x0027  /**< Camellia hardware accelerator failed. */
 
-#if !defined(MBEDTLS_CAMELLIA_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_CAMELLIA_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          CAMELLIA context structure
  */
@@ -58,6 +58,10 @@
 }
 mbedtls_camellia_context;
 
+#else  /* MBEDTLS_CAMELLIA_ALT */
+#include "camellia_alt.h"
+#endif /* MBEDTLS_CAMELLIA_ALT */
+
 /**
  * \brief          Initialize CAMELLIA context
  *
@@ -211,18 +215,6 @@
                        unsigned char *output );
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_CAMELLIA_ALT */
-#include "camellia_alt.h"
-#endif /* MBEDTLS_CAMELLIA_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Checkup routine
  *
diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h
index 5a34f3a..8585ce5 100644
--- a/include/mbedtls/ccm.h
+++ b/include/mbedtls/ccm.h
@@ -43,14 +43,15 @@
 #define MBEDTLS_ERR_CCM_AUTH_FAILED     -0x000F /**< Authenticated decryption failed. */
 #define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
 
-#if !defined(MBEDTLS_CCM_ALT)
-// Regular implementation
-//
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_CCM_ALT)
+// Regular implementation
+//
+
 /**
  * \brief    The CCM context-type definition. The CCM context is passed
  *           to the APIs called.
@@ -60,6 +61,10 @@
 }
 mbedtls_ccm_context;
 
+#else  /* MBEDTLS_CCM_ALT */
+#include "ccm_alt.h"
+#endif /* MBEDTLS_CCM_ALT */
+
 /**
  * \brief           This function initializes the specified CCM context,
  *                  to make references valid, and prepare the context
@@ -155,17 +160,6 @@
                       const unsigned char *input, unsigned char *output,
                       const unsigned char *tag, size_t tag_len );
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_CCM_ALT */
-#include "ccm_alt.h"
-#endif /* MBEDTLS_CCM_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
 /**
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index be80332..4689f3a 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -4,7 +4,7 @@
  * \brief Consistency checks for configuration options
  */
 /*
- *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -191,6 +191,10 @@
 #error "MBEDTLS_HAVEGE_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C)
+#error "MBEDTLS_HKDF_C defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C)
 #error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites"
 #endif
diff --git a/include/mbedtls/cmac.h b/include/mbedtls/cmac.h
index 0ada742..913c05f 100644
--- a/include/mbedtls/cmac.h
+++ b/include/mbedtls/cmac.h
@@ -63,6 +63,10 @@
     size_t              unprocessed_len;
 };
 
+#else  /* !MBEDTLS_CMAC_ALT */
+#include "cmac_alt.h"
+#endif /* !MBEDTLS_CMAC_ALT */
+
 /**
  * \brief               This function sets the CMAC key, and prepares to authenticate
  *                      the input data.
@@ -185,18 +189,6 @@
                               unsigned char output[16] );
 #endif /* MBEDTLS_AES_C */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* !MBEDTLS_CMAC_ALT */
-#include "cmac_alt.h"
-#endif /* !MBEDTLS_CMAC_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )
 /**
  * \brief          The CMAC checkup routine.
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 1b4bee3..86cb6d1 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -8,7 +8,7 @@
  *  memory footprint.
  */
 /*
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -2099,6 +2099,21 @@
 //#define MBEDTLS_HAVEGE_C
 
 /**
+ * \def MBEDTLS_HKDF_C
+ *
+ * Enable HKDF algorithm.
+ *
+ * Module:  library/hkdf.c
+ * Caller:
+
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the Hashed Message Authentication Code
+ * (HMAC)-based key derivation function (HKDF).
+ */
+#define MBEDTLS_HKDF_C
+
+/**
  * \def MBEDTLS_HMAC_DRBG_C
  *
  * Enable the HMAC_DRBG random generator.
@@ -2859,6 +2874,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/des.h b/include/mbedtls/des.h
index 5a1a636..6eb7d03 100644
--- a/include/mbedtls/des.h
+++ b/include/mbedtls/des.h
@@ -46,14 +46,14 @@
 
 #define MBEDTLS_DES_KEY_SIZE    8
 
-#if !defined(MBEDTLS_DES_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_DES_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          DES context structure
  *
@@ -76,6 +76,10 @@
 }
 mbedtls_des3_context;
 
+#else  /* MBEDTLS_DES_ALT */
+#include "des_alt.h"
+#endif /* MBEDTLS_DES_ALT */
+
 /**
  * \brief          Initialize DES context
  *
@@ -331,17 +335,6 @@
  */
 void mbedtls_des_setkey( uint32_t SK[32],
                          const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_DES_ALT */
-#include "des_alt.h"
-#endif /* MBEDTLS_DES_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 /**
  * \brief          Checkup routine
diff --git a/include/mbedtls/dhm.h b/include/mbedtls/dhm.h
index b3b3761..f848e22 100644
--- a/include/mbedtls/dhm.h
+++ b/include/mbedtls/dhm.h
@@ -71,7 +71,6 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 #include "bignum.h"
-#if !defined(MBEDTLS_DHM_ALT)
 
 /*
  * DHM Error codes
@@ -92,6 +91,8 @@
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_DHM_ALT)
+
 /**
  * \brief          The DHM context structure.
  */
@@ -111,6 +112,10 @@
 }
 mbedtls_dhm_context;
 
+#else /* MBEDTLS_DHM_ALT */
+#include "dhm_alt.h"
+#endif /* MBEDTLS_DHM_ALT */
+
 /**
  * \brief          This function initializes the DHM context.
  *
@@ -290,18 +295,6 @@
 #endif /* MBEDTLS_FS_IO */
 #endif /* MBEDTLS_ASN1_PARSE_C */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else /* MBEDTLS_DHM_ALT */
-#include "dhm_alt.h"
-#endif /* MBEDTLS_DHM_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          The DMH checkup routine.
  *
diff --git a/include/mbedtls/ecjpake.h b/include/mbedtls/ecjpake.h
index d86e820..cc2b316 100644
--- a/include/mbedtls/ecjpake.h
+++ b/include/mbedtls/ecjpake.h
@@ -44,8 +44,6 @@
 #include "ecp.h"
 #include "md.h"
 
-#if !defined(MBEDTLS_ECJPAKE_ALT)
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -58,6 +56,7 @@
     MBEDTLS_ECJPAKE_SERVER,             /**< Server                         */
 } mbedtls_ecjpake_role;
 
+#if !defined(MBEDTLS_ECJPAKE_ALT)
 /**
  * EC J-PAKE context structure.
  *
@@ -88,6 +87,10 @@
     mbedtls_mpi s;                      /**< Pre-shared secret (passphrase) */
 } mbedtls_ecjpake_context;
 
+#else  /* MBEDTLS_ECJPAKE_ALT */
+#include "ecjpake_alt.h"
+#endif /* MBEDTLS_ECJPAKE_ALT */
+
 /**
  * \brief           Initialize a context
  *                  (just makes it ready for setup() or free()).
@@ -225,20 +228,10 @@
  */
 void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx );
 
-#ifdef __cplusplus
-}
-#endif
 
-#else  /* MBEDTLS_ECJPAKE_ALT */
-#include "ecjpake_alt.h"
-#endif /* MBEDTLS_ECJPAKE_ALT */
 
 #if defined(MBEDTLS_SELF_TEST)
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Checkup routine
  *
@@ -246,10 +239,11 @@
  */
 int mbedtls_ecjpake_self_test( int verbose );
 
+#endif /* MBEDTLS_SELF_TEST */
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* MBEDTLS_SELF_TEST */
 
 #endif /* ecjpake.h */
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index 9fc650e..3a40798 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -51,15 +51,6 @@
 #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH                  -0x4C00  /**< The buffer contains a valid signature followed by more data. */
 #define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED                   -0x4B80  /**< The ECP hardware accelerator failed. */
 
-#if !defined(MBEDTLS_ECP_ALT)
-/*
- * default mbed TLS elliptic curve arithmetic implementation
- *
- * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an
- * alternative implementation for the whole module and it will replace this
- * one.)
- */
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -85,10 +76,10 @@
     MBEDTLS_ECP_DP_BP384R1,        /*!< Domain parameters for 384-bit Brainpool curve. */
     MBEDTLS_ECP_DP_BP512R1,        /*!< Domain parameters for 512-bit Brainpool curve. */
     MBEDTLS_ECP_DP_CURVE25519,     /*!< Domain parameters for Curve25519. */
-    MBEDTLS_ECP_DP_CURVE448,       /*!< Domain parameters for Curve448. */
     MBEDTLS_ECP_DP_SECP192K1,      /*!< Domain parameters for 192-bit "Koblitz" curve. */
     MBEDTLS_ECP_DP_SECP224K1,      /*!< Domain parameters for 224-bit "Koblitz" curve. */
     MBEDTLS_ECP_DP_SECP256K1,      /*!< Domain parameters for 256-bit "Koblitz" curve. */
+    MBEDTLS_ECP_DP_CURVE448,       /*!< Domain parameters for Curve448. */
 } mbedtls_ecp_group_id;
 
 /**
@@ -128,6 +119,15 @@
 }
 mbedtls_ecp_point;
 
+#if !defined(MBEDTLS_ECP_ALT)
+/*
+ * default mbed TLS elliptic curve arithmetic implementation
+ *
+ * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an
+ * alternative implementation for the whole module and it will replace this
+ * one.)
+ */
+
 /**
  * \brief           The ECP group structure.
  *
@@ -182,22 +182,6 @@
 mbedtls_ecp_group;
 
 /**
- * \brief    The ECP key-pair structure.
- *
- * A generic key-pair that may be used for ECDSA and fixed ECDH, for example.
- *
- * \note    Members are deliberately in the same order as in the
- *          ::mbedtls_ecdsa_context structure.
- */
-typedef struct
-{
-    mbedtls_ecp_group grp;      /*!<  The elliptic curve and base point. */
-    mbedtls_mpi d;              /*!<  Our secret value. */
-    mbedtls_ecp_point Q;        /*!<  Our public value. */
-}
-mbedtls_ecp_keypair;
-
-/**
  * \name SECTION: Module settings
  *
  * The configuration options you can set for this module are in this section.
@@ -255,6 +239,26 @@
 
 /* \} name SECTION: Module settings */
 
+#else  /* MBEDTLS_ECP_ALT */
+#include "ecp_alt.h"
+#endif /* MBEDTLS_ECP_ALT */
+
+/**
+ * \brief    The ECP key-pair structure.
+ *
+ * A generic key-pair that may be used for ECDSA and fixed ECDH, for example.
+ *
+ * \note    Members are deliberately in the same order as in the
+ *          ::mbedtls_ecdsa_context structure.
+ */
+typedef struct
+{
+    mbedtls_ecp_group grp;      /*!<  Elliptic curve and base point     */
+    mbedtls_mpi d;              /*!<  our secret value                  */
+    mbedtls_ecp_point Q;        /*!<  our public value                  */
+}
+mbedtls_ecp_keypair;
+
 /*
  * Point formats, from RFC 4492's enum ECPointFormat
  */
@@ -757,8 +761,4 @@
 }
 #endif
 
-#else  /* MBEDTLS_ECP_ALT */
-#include "ecp_alt.h"
-#endif /* MBEDTLS_ECP_ALT */
-
 #endif /* ecp.h */
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index 8b4d3a8..a3d6bba 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -4,7 +4,7 @@
  * \brief Error to string translation
  */
 /*
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -88,6 +88,7 @@
  * RSA       4   11
  * ECP       4   9 (Started from top)
  * MD        5   5
+ * HKDF      5   1
  * CIPHER    6   8
  * SSL       6   17 (Started from top)
  * SSL       7   31
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index 119e275..3c22033 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -44,12 +44,12 @@
 #define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED                   -0x0013  /**< GCM hardware accelerator failed. */
 #define MBEDTLS_ERR_GCM_BAD_INPUT                         -0x0014  /**< Bad input parameters to function. */
 
-#if !defined(MBEDTLS_GCM_ALT)
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_GCM_ALT)
+
 /**
  * \brief          The GCM context structure.
  */
@@ -68,6 +68,10 @@
 }
 mbedtls_gcm_context;
 
+#else  /* !MBEDTLS_GCM_ALT */
+#include "gcm_alt.h"
+#endif /* !MBEDTLS_GCM_ALT */
+
 /**
  * \brief           This function initializes the specified GCM context,
  *                  to make references valid, and prepares the context
@@ -246,18 +250,6 @@
  */
 void mbedtls_gcm_free( mbedtls_gcm_context *ctx );
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* !MBEDTLS_GCM_ALT */
-#include "gcm_alt.h"
-#endif /* !MBEDTLS_GCM_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          The GCM checkup routine.
  *
diff --git a/include/mbedtls/hkdf.h b/include/mbedtls/hkdf.h
new file mode 100644
index 0000000..419c34e
--- /dev/null
+++ b/include/mbedtls/hkdf.h
@@ -0,0 +1,115 @@
+/**
+ * \file hkdf.h
+ *
+ * \brief The HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
+ *
+ */
+/*
+ * Copyright (C) 2016-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_HKDF_H
+#define MBEDTLS_HKDF_H
+
+#include "md.h"
+
+/**
+ *  \name HKDF Error codes
+ *  \{
+ */
+#define MBEDTLS_ERR_HKDF_BAD_PARAM  -0x5300  /**< Bad parameter */
+/* \} name */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  \brief  HMAC-based Extract-and-Expand Key Derivation Function
+ *
+ *  \param  md        a hash function; md.size denotes the length of the hash
+ *                    function output in bytes
+ *  \param  salt      optional salt value (a non-secret random value);
+ *                    if not provided, it is set to a string of md.size zeros.
+ *  \param  salt_len  length in bytes of the optional \p salt
+ *  \param  ikm       input keying material
+ *  \param  ikm_len   length in bytes of \p ikm
+ *  \param  info      optional context and application specific information
+ *                    (can be a zero-length string)
+ *  \param  info_len  length of \p info in bytes
+ *  \param  okm       output keying material (of \p okm_len bytes)
+ *  \param  okm_len   length of output keying material in octets
+ *                    (<= 255*md.size)
+ *
+ *  \return 0 on success or one of the failure codes from mbedtls_hkdf_extract
+ *          or mbedtls_hkdf_expand
+ */
+int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
+                  size_t salt_len, const unsigned char *ikm, size_t ikm_len,
+                  const unsigned char *info, size_t info_len,
+                  unsigned char *okm, size_t okm_len );
+
+/**
+ *  \brief  Take the input keying material \p ikm and extract from it a
+ *          fixed-length pseudorandom key \p prk
+ *
+ *  \param       md        a hash function; md.size denotes the length of the
+ *                         hash function output in bytes
+ *  \param       salt      optional salt value (a non-secret random value);
+ *                         if not provided, it is set to a string of md.size
+ *                         zeros.
+ *  \param       salt_len  length in bytes of the optional \p salt
+ *  \param       ikm       input keying material
+ *  \param       ikm_len   length in bytes of \p ikm
+ *  \param[out]  prk       a pseudorandom key of md.size bytes
+ *
+ *  \return 0 on success, MBEDTLS_ERR_HKDF_BAD_PARAM or one of mbedtls_md_*
+ *          error codes on failure
+ */
+int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
+                          const unsigned char *salt, size_t salt_len,
+                          const unsigned char *ikm, size_t ikm_len,
+                          unsigned char *prk );
+
+/**
+ *  \brief  Expand the supplied \p prk into several additional pseudorandom keys
+ *          (the output of the KDF).
+ *
+ *  \param  md          a hash function; md.size denotes the length of the hash
+ *                      function output in bytes
+ *  \param  prk         a pseudorandom key of at least md.size bytes; usually,
+ *                      the output from the extract step
+ *  \param  prk_len     length of \p prk in bytes
+ *  \param  info        optional context and application specific information
+ *                      (can be a zero-length string)
+ *  \param  info_len    length of \p info in bytes
+ *  \param  okm         output keying material (of \p okm_len bytes)
+ *  \param  okm_len     length of output keying material in octets
+ *                      (<= 255*md.size)
+ *
+ *  \return 0 on success, MBEDTLS_ERR_HKDF_BAD_PARAM or a failure code from the
+ *          mbedtls_md_* family
+ */
+int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
+                         size_t prk_len, const unsigned char *info,
+                         size_t info_len, unsigned char *okm, size_t okm_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* hkdf.h */
diff --git a/include/mbedtls/md2.h b/include/mbedtls/md2.h
index 0fd8b5a..08e75b2 100644
--- a/include/mbedtls/md2.h
+++ b/include/mbedtls/md2.h
@@ -39,14 +39,14 @@
 
 #define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED                   -0x002B  /**< MD2 hardware accelerator failed */
 
-#if !defined(MBEDTLS_MD2_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_MD2_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          MD2 context structure
  *
@@ -64,6 +64,10 @@
 }
 mbedtls_md2_context;
 
+#else  /* MBEDTLS_MD2_ALT */
+#include "md2_alt.h"
+#endif /* MBEDTLS_MD2_ALT */
+
 /**
  * \brief          Initialize MD2 context
  *
@@ -235,18 +239,6 @@
 #undef MBEDTLS_DEPRECATED
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_MD2_ALT */
-#include "md2_alt.h"
-#endif /* MBEDTLS_MD2_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Output = MD2( input buffer )
  *
diff --git a/include/mbedtls/md4.h b/include/mbedtls/md4.h
index 23fa95e..8ee4e5c 100644
--- a/include/mbedtls/md4.h
+++ b/include/mbedtls/md4.h
@@ -40,14 +40,14 @@
 
 #define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED                   -0x002D  /**< MD4 hardware accelerator failed */
 
-#if !defined(MBEDTLS_MD4_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_MD4_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          MD4 context structure
  *
@@ -64,6 +64,10 @@
 }
 mbedtls_md4_context;
 
+#else  /* MBEDTLS_MD4_ALT */
+#include "md4_alt.h"
+#endif /* MBEDTLS_MD4_ALT */
+
 /**
  * \brief          Initialize MD4 context
  *
@@ -238,18 +242,6 @@
 #undef MBEDTLS_DEPRECATED
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_MD4_ALT */
-#include "md4_alt.h"
-#endif /* MBEDTLS_MD4_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Output = MD4( input buffer )
  *
diff --git a/include/mbedtls/md5.h b/include/mbedtls/md5.h
index 06ea4c5..43ead4b 100644
--- a/include/mbedtls/md5.h
+++ b/include/mbedtls/md5.h
@@ -39,14 +39,14 @@
 
 #define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED                   -0x002F  /**< MD5 hardware accelerator failed */
 
-#if !defined(MBEDTLS_MD5_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_MD5_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          MD5 context structure
  *
@@ -63,6 +63,10 @@
 }
 mbedtls_md5_context;
 
+#else  /* MBEDTLS_MD5_ALT */
+#include "md5_alt.h"
+#endif /* MBEDTLS_MD5_ALT */
+
 /**
  * \brief          Initialize MD5 context
  *
@@ -238,18 +242,6 @@
 #undef MBEDTLS_DEPRECATED
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_MD5_ALT */
-#include "md5_alt.h"
-#endif /* MBEDTLS_MD5_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Output = MD5( input buffer )
  *
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index d50b266..a53229b 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -223,7 +223,7 @@
 #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
 #define mbedtls_snprintf   MBEDTLS_PLATFORM_SNPRINTF_MACRO
 #else
-#define mbedtls_snprintf   snprintf
+#define mbedtls_snprintf   MBEDTLS_PLATFORM_STD_SNPRINTF
 #endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */
 #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
 
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/include/mbedtls/ripemd160.h b/include/mbedtls/ripemd160.h
index 3a8b50a..a0dac0c 100644
--- a/include/mbedtls/ripemd160.h
+++ b/include/mbedtls/ripemd160.h
@@ -35,14 +35,14 @@
 
 #define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED             -0x0031  /**< RIPEMD160 hardware accelerator failed */
 
-#if !defined(MBEDTLS_RIPEMD160_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_RIPEMD160_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          RIPEMD-160 context structure
  */
@@ -54,6 +54,10 @@
 }
 mbedtls_ripemd160_context;
 
+#else  /* MBEDTLS_RIPEMD160_ALT */
+#include "ripemd160.h"
+#endif /* MBEDTLS_RIPEMD160_ALT */
+
 /**
  * \brief          Initialize RIPEMD-160 context
  *
@@ -178,18 +182,6 @@
 #undef MBEDTLS_DEPRECATED
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_RIPEMD160_ALT */
-#include "ripemd160_alt.h"
-#endif /* MBEDTLS_RIPEMD160_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Output = RIPEMD-160( input buffer )
  *
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index f8b8965..df6e3e5 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -77,14 +77,14 @@
  * eg for alternative (PKCS#11) RSA implemenations in the PK layers.
  */
 
-#if !defined(MBEDTLS_RSA_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_RSA_ALT)
+// Regular implementation
+//
+
 /**
  * \brief   The RSA context structure.
  *
@@ -129,6 +129,10 @@
 }
 mbedtls_rsa_context;
 
+#else  /* MBEDTLS_RSA_ALT */
+#include "rsa_alt.h"
+#endif /* MBEDTLS_RSA_ALT */
+
 /**
  * \brief          This function initializes an RSA context.
  *
@@ -1112,18 +1116,6 @@
  */
 void mbedtls_rsa_free( mbedtls_rsa_context *ctx );
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_RSA_ALT */
-#include "rsa_alt.h"
-#endif /* MBEDTLS_RSA_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          The RSA checkup routine.
  *
diff --git a/include/mbedtls/sha1.h b/include/mbedtls/sha1.h
index eec3f95..8f805fb 100644
--- a/include/mbedtls/sha1.h
+++ b/include/mbedtls/sha1.h
@@ -42,14 +42,14 @@
 
 #define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED                  -0x0035  /**< SHA-1 hardware accelerator failed */
 
-#if !defined(MBEDTLS_SHA1_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_SHA1_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          The SHA-1 context structure.
  *
@@ -66,6 +66,10 @@
 }
 mbedtls_sha1_context;
 
+#else  /* MBEDTLS_SHA1_ALT */
+#include "sha1_alt.h"
+#endif /* MBEDTLS_SHA1_ALT */
+
 /**
  * \brief          This function initializes a SHA-1 context.
  *
@@ -243,18 +247,6 @@
 #undef MBEDTLS_DEPRECATED
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_SHA1_ALT */
-#include "sha1_alt.h"
-#endif /* MBEDTLS_SHA1_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          This function calculates the SHA-1 checksum of a buffer.
  *
diff --git a/include/mbedtls/sha256.h b/include/mbedtls/sha256.h
index c4465e5..adf31a8 100644
--- a/include/mbedtls/sha256.h
+++ b/include/mbedtls/sha256.h
@@ -38,14 +38,14 @@
 
 #define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED                -0x0037  /**< SHA-256 hardware accelerator failed */
 
-#if !defined(MBEDTLS_SHA256_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_SHA256_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          The SHA-256 context structure.
  *
@@ -63,6 +63,10 @@
 }
 mbedtls_sha256_context;
 
+#else  /* MBEDTLS_SHA256_ALT */
+#include "sha256_alt.h"
+#endif /* MBEDTLS_SHA256_ALT */
+
 /**
  * \brief          This function initializes a SHA-256 context.
  *
@@ -198,17 +202,6 @@
 
 #undef MBEDTLS_DEPRECATED
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_SHA256_ALT */
-#include "sha256_alt.h"
-#endif /* MBEDTLS_SHA256_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 /**
  * \brief          This function calculates the SHA-224 or SHA-256
diff --git a/include/mbedtls/sha512.h b/include/mbedtls/sha512.h
index ee88fcf..5bb83f4 100644
--- a/include/mbedtls/sha512.h
+++ b/include/mbedtls/sha512.h
@@ -37,14 +37,14 @@
 
 #define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED                -0x0039  /**< SHA-512 hardware accelerator failed */
 
-#if !defined(MBEDTLS_SHA512_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_SHA512_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          The SHA-512 context structure.
  *
@@ -62,6 +62,10 @@
 }
 mbedtls_sha512_context;
 
+#else  /* MBEDTLS_SHA512_ALT */
+#include "sha512_alt.h"
+#endif /* MBEDTLS_SHA512_ALT */
+
 /**
  * \brief          This function initializes a SHA-512 context.
  *
@@ -197,18 +201,6 @@
 #undef MBEDTLS_DEPRECATED
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_SHA512_ALT */
-#include "sha512_alt.h"
-#endif /* MBEDTLS_SHA512_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          This function calculates the SHA-512 or SHA-384
  *                 checksum of a buffer.
diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h
index 2c497bf..bbcb906 100644
--- a/include/mbedtls/timing.h
+++ b/include/mbedtls/timing.h
@@ -30,16 +30,16 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
-#if !defined(MBEDTLS_TIMING_ALT)
-// Regular implementation
-//
-
 #include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_TIMING_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          timer structure
  */
@@ -58,6 +58,10 @@
     uint32_t                        fin_ms;
 } mbedtls_timing_delay_context;
 
+#else  /* MBEDTLS_TIMING_ALT */
+#include "timing_alt.h"
+#endif /* MBEDTLS_TIMING_ALT */
+
 extern volatile int mbedtls_timing_alarmed;
 
 /**
@@ -133,18 +137,6 @@
  */
 int mbedtls_timing_get_delay( void *data );
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_TIMING_ALT */
-#include "timing_alt.h"
-#endif /* MBEDTLS_TIMING_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #if defined(MBEDTLS_SELF_TEST)
 /**
  * \brief          Checkup routine
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index c3ee649..aa52ce2 100644
--- a/include/mbedtls/version.h
+++ b/include/mbedtls/version.h
@@ -39,7 +39,7 @@
  * Major, Minor, Patchlevel
  */
 #define MBEDTLS_VERSION_MAJOR  2
-#define MBEDTLS_VERSION_MINOR  8
+#define MBEDTLS_VERSION_MINOR  9
 #define MBEDTLS_VERSION_PATCH  0
 
 /**
@@ -47,9 +47,9 @@
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x02080000
-#define MBEDTLS_VERSION_STRING         "2.8.0"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.8.0"
+#define MBEDTLS_VERSION_NUMBER         0x02090000
+#define MBEDTLS_VERSION_STRING         "2.9.0"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.9.0"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/include/mbedtls/xtea.h b/include/mbedtls/xtea.h
index 34ccee3..8df708a 100644
--- a/include/mbedtls/xtea.h
+++ b/include/mbedtls/xtea.h
@@ -39,14 +39,14 @@
 #define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH             -0x0028  /**< The data input has an invalid length. */
 #define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED                  -0x0029  /**< XTEA hardware accelerator failed. */
 
-#if !defined(MBEDTLS_XTEA_ALT)
-// Regular implementation
-//
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_XTEA_ALT)
+// Regular implementation
+//
+
 /**
  * \brief          XTEA context structure
  */
@@ -56,6 +56,10 @@
 }
 mbedtls_xtea_context;
 
+#else  /* MBEDTLS_XTEA_ALT */
+#include "xtea_alt.h"
+#endif /* MBEDTLS_XTEA_ALT */
+
 /**
  * \brief          Initialize XTEA context
  *
@@ -115,18 +119,6 @@
                     unsigned char *output);
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
-#ifdef __cplusplus
-}
-#endif
-
-#else  /* MBEDTLS_XTEA_ALT */
-#include "xtea_alt.h"
-#endif /* MBEDTLS_XTEA_ALT */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * \brief          Checkup routine
  *
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 7742c22..b730d08 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -29,6 +29,7 @@
     error.c
     gcm.c
     havege.c
+    hkdf.c
     hmac_drbg.c
     md.c
     md2.c
@@ -46,6 +47,7 @@
     pkparse.c
     pkwrite.c
     platform.c
+    platform_util.c
     ripemd160.c
     rsa.c
     rsa_internal.c
@@ -141,15 +143,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.8.0 SOVERSION 1)
+    set_target_properties(mbedcrypto PROPERTIES VERSION 2.9.0 SOVERSION 2)
     target_link_libraries(mbedcrypto ${libs})
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.8.0 SOVERSION 0)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.9.0 SOVERSION 0)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.8.0 SOVERSION 10)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.9.0 SOVERSION 10)
     target_link_libraries(mbedtls ${libs} mbedx509)
 
     install(TARGETS mbedtls mbedx509 mbedcrypto
diff --git a/library/Makefile b/library/Makefile
index 0333815..5721d7e 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -33,7 +33,7 @@
 
 SOEXT_TLS=so.10
 SOEXT_X509=so.0
-SOEXT_CRYPTO=so.1
+SOEXT_CRYPTO=so.2
 
 # Set DLEXT=dylib to compile as a shared library for Mac OS X
 DLEXT ?= so
@@ -56,16 +56,18 @@
 		ecjpake.o	ecp.o				\
 		ecp_curves.o	entropy.o	entropy_poll.o	\
 		error.o		gcm.o		havege.o	\
+		hkdf.o						\
 		hmac_drbg.o	md.o		md2.o		\
 		md4.o		md5.o		md_wrap.o	\
 		memory_buffer_alloc.o		oid.o		\
 		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 46d5463..22eb53c 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 0713fee..2c599e5 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/error.c b/library/error.c
index 222d85b..8dd90b2 100644
--- a/library/error.c
+++ b/library/error.c
@@ -101,6 +101,10 @@
 #include "mbedtls/gcm.h"
 #endif
 
+#if defined(MBEDTLS_HKDF_C)
+#include "mbedtls/hkdf.h"
+#endif
+
 #if defined(MBEDTLS_HMAC_DRBG_C)
 #include "mbedtls/hmac_drbg.h"
 #endif
@@ -698,6 +702,11 @@
         mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" );
 #endif /* MBEDTLS_GCM_C */
 
+#if defined(MBEDTLS_HKDF_C)
+    if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_PARAM) )
+        mbedtls_snprintf( buf, buflen, "HKDF - Bad parameter" );
+#endif /* MBEDTLS_HKDF_C */
+
 #if defined(MBEDTLS_HMAC_DRBG_C)
     if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) )
         mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
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/hkdf.c b/library/hkdf.c
new file mode 100644
index 0000000..ded555c
--- /dev/null
+++ b/library/hkdf.c
@@ -0,0 +1,164 @@
+/*
+ *  HKDF implementation -- RFC 5869
+ *
+ *  Copyright (C) 2016-2017, 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
+
+#if defined(MBEDTLS_HKDF_C)
+
+#include <string.h>
+#include "mbedtls/hkdf.h"
+#include "mbedtls/platform_util.h"
+
+/* HKDF-Extract + HKDF-Expand */
+int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
+                  size_t salt_len, const unsigned char *ikm, size_t ikm_len,
+                  const unsigned char *info, size_t info_len,
+                  unsigned char *okm, size_t okm_len )
+{
+    int ret;
+    unsigned char prk[MBEDTLS_MD_MAX_SIZE];
+
+    ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk );
+
+    if ( ret == 0 ) {
+        ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size(md), info, info_len, okm, okm_len );
+    }
+
+    mbedtls_platform_zeroize( prk, sizeof( prk ) );
+
+    return( ret );
+}
+
+/* HKDF-Extract(salt, IKM) -> PRK */
+int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
+                          const unsigned char *salt, size_t salt_len,
+                          const unsigned char *ikm, size_t ikm_len,
+                          unsigned char *prk )
+{
+    unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' };
+
+    if ( salt == NULL ) {
+        size_t hash_len;
+
+        hash_len = mbedtls_md_get_size( md );
+
+        if ( hash_len == 0 ) {
+            return MBEDTLS_ERR_HKDF_BAD_PARAM;
+        }
+
+        salt = null_salt;
+        salt_len = hash_len;
+    }
+
+    return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) );
+}
+
+/* HKDF-Expand(PRK, info, L) -> OKM */
+int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
+                         size_t prk_len, const unsigned char *info,
+                         size_t info_len, unsigned char *okm, size_t okm_len )
+{
+    size_t hash_len;
+    size_t where = 0;
+    size_t N;
+    size_t T_len = 0;
+    size_t i;
+    int ret = 0;
+    mbedtls_md_context_t ctx;
+    unsigned char T[MBEDTLS_MD_MAX_SIZE];
+
+    if ( okm == NULL ) {
+        return( MBEDTLS_ERR_HKDF_BAD_PARAM );
+    }
+
+    hash_len = mbedtls_md_get_size(md);
+
+    if ( (prk_len < hash_len) || (hash_len == 0) ) {
+        return( MBEDTLS_ERR_HKDF_BAD_PARAM );
+    }
+
+    if ( info == NULL ) {
+        info = (const unsigned char *) "";
+        info_len = 0;
+    }
+
+    N = okm_len / hash_len;
+
+    if ( (okm_len % hash_len) != 0 ) {
+        N++;
+    }
+
+    if ( N > 255 ) {
+        return( MBEDTLS_ERR_HKDF_BAD_PARAM );
+    }
+
+    mbedtls_md_init( &ctx );
+
+    if ( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) {
+        goto exit;
+    }
+
+    /* Section 2.3. */
+    for ( i = 1; i <= N; i++ ) {
+        unsigned char c = i & 0xff;
+
+        ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len );
+        if ( ret != 0 ) {
+            goto exit;
+        }
+
+        ret = mbedtls_md_hmac_update( &ctx, T, T_len );
+        if ( ret != 0 ) {
+            goto exit;
+        }
+
+        ret = mbedtls_md_hmac_update( &ctx, info, info_len );
+        if ( ret != 0 ) {
+            goto exit;
+        }
+
+        /* The constant concatenated to the end of each T(n) is a single octet.
+         * */
+        ret = mbedtls_md_hmac_update( &ctx, &c, 1 );
+        if ( ret != 0 ) {
+            goto exit;
+        }
+
+        ret = mbedtls_md_hmac_finish( &ctx, T );
+        if ( ret != 0 ) {
+            goto exit;
+        }
+
+        memcpy( okm + where, T, (i != N) ? hash_len : (okm_len - where) );
+        where += hash_len;
+        T_len = hash_len;
+    }
+
+exit:
+    mbedtls_md_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_HKDF_C */
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 738014e..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)
@@ -717,6 +714,49 @@
     return( 0 );
 }
 
+/**
+ * \brief           Validate cipher suite against config in SSL context.
+ *
+ * \param suite_info    cipher suite to validate
+ * \param ssl           SSL context
+ * \param min_minor_ver Minimal minor version to accept a cipher suite
+ * \param max_minor_ver Maximal minor version to accept a cipher suite
+ *
+ * \return          0 if valid, else 1
+ */
+static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info,
+                                     const mbedtls_ssl_context * ssl,
+                                     int min_minor_ver, int max_minor_ver )
+{
+    (void) ssl;
+    if( suite_info == NULL )
+        return( 1 );
+
+    if( suite_info->min_minor_ver > max_minor_ver ||
+            suite_info->max_minor_ver < min_minor_ver )
+        return( 1 );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+            ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
+        return( 1 );
+#endif
+
+#if defined(MBEDTLS_ARC4_C)
+    if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
+            suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
+        return( 1 );
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
+            mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
+        return( 1 );
+#endif
+
+    return( 0 );
+}
+
 static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -869,31 +909,11 @@
     {
         ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] );
 
-        if( ciphersuite_info == NULL )
+        if( ssl_validate_ciphersuite( ciphersuite_info, ssl,
+                                      ssl->conf->min_minor_ver,
+                                      ssl->conf->max_minor_ver ) != 0 )
             continue;
 
-        if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver ||
-            ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver )
-            continue;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-            ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
-            continue;
-#endif
-
-#if defined(MBEDTLS_ARC4_C)
-        if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
-            ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
-            continue;
-#endif
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
-            mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
-            continue;
-#endif
-
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x",
                                     ciphersuites[i] ) );
 
@@ -1690,22 +1710,9 @@
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) );
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) );
 
-    suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite );
-    if( suite_info == NULL
-#if defined(MBEDTLS_ARC4_C)
-            || ( ssl->conf->arc4_disabled &&
-                suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
-#endif
-        )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
-
+    /*
+     * Perform cipher suite validation in same way as in ssl_write_client_hello.
+     */
     i = 0;
     while( 1 )
     {
@@ -1724,6 +1731,17 @@
         }
     }
 
+    suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite );
+    if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, ssl->minor_ver ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
+
     if( comp != MBEDTLS_SSL_COMPRESS_NULL
 #if defined(MBEDTLS_ZLIB_SUPPORT)
         && comp != MBEDTLS_SSL_COMPRESS_DEFLATE
@@ -2673,10 +2691,27 @@
     buf = ssl->in_msg;
 
     /* certificate_types */
+    if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+    }
     cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )];
     n = cert_type_len;
 
-    if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
+    /*
+     * In the subsequent code there are two paths that read from buf:
+     *     * the length of the signature algorithms field (if minor version of
+     *       SSL is 3),
+     *     * distinguished name length otherwise.
+     * Both reach at most the index:
+     *    ...hdr_len + 2 + n,
+     * therefore the buffer length at this point must be greater than that
+     * regardless of the actual code path.
+     */
+    if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -2691,9 +2726,32 @@
         size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] <<  8 )
                              | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n]       ) );
 #if defined(MBEDTLS_DEBUG_C)
-        unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n;
+        unsigned char* sig_alg;
         size_t i;
+#endif
 
+        /*
+         * The furthest access in buf is in the loop few lines below:
+         *     sig_alg[i + 1],
+         * where:
+         *     sig_alg = buf + ...hdr_len + 3 + n,
+         *     max(i) = sig_alg_len - 1.
+         * Therefore the furthest access is:
+         *     buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1],
+         * which reduces to:
+         *     buf[...hdr_len + 3 + n + sig_alg_len],
+         * which is one less than we need the buf to be.
+         */
+        if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n + sig_alg_len )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
+            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+        }
+
+#if defined(MBEDTLS_DEBUG_C)
+        sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n;
         for( i = 0; i < sig_alg_len; i += 2 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d"
@@ -2702,14 +2760,6 @@
 #endif
 
         n += 2 + sig_alg_len;
-
-        if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
-        }
     }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
@@ -3289,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/version_features.c b/library/version_features.c
index 218a892..b462e42 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -582,6 +582,9 @@
 #if defined(MBEDTLS_HAVEGE_C)
     "MBEDTLS_HAVEGE_C",
 #endif /* MBEDTLS_HAVEGE_C */
+#if defined(MBEDTLS_HKDF_C)
+    "MBEDTLS_HKDF_C",
+#endif /* MBEDTLS_HKDF_C */
 #if defined(MBEDTLS_HMAC_DRBG_C)
     "MBEDTLS_HMAC_DRBG_C",
 #endif /* MBEDTLS_HMAC_DRBG_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/scripts/generate_errors.pl b/scripts/generate_errors.pl
index ac0fbff..7290b87 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -31,7 +31,7 @@
 
 my @low_level_modules = qw( AES ARC4 ASN1 BASE64 BIGNUM BLOWFISH
                             CAMELLIA CCM CMAC CTR_DRBG DES
-                            ENTROPY GCM HMAC_DRBG MD2 MD4 MD5
+                            ENTROPY GCM HKDF HMAC_DRBG MD2 MD4 MD5
                             NET OID PADLOCK PBKDF2 RIPEMD160
                             SHA1 SHA256 SHA512 THREADING XTEA );
 my @high_level_modules = qw( CIPHER DHM ECP MD
diff --git a/scripts/output_env.sh b/scripts/output_env.sh
index 1afaac3..e9ad8c5 100755
--- a/scripts/output_env.sh
+++ b/scripts/output_env.sh
@@ -47,13 +47,15 @@
 print_version "uname" "-a" ""
 echo
 
-: ${ARMC5_CC:=armcc}
-print_version "$ARMC5_CC" "--vsn" "armcc not found!" "head -n 2"
-echo
+if [ "${RUN_ARMCC:-1}" -ne 0 ]; then
+    : "${ARMC5_CC:=armcc}"
+    print_version "$ARMC5_CC" "--vsn" "armcc not found!" "head -n 2"
+    echo
 
-: ${ARMC6_CC:=armclang}
-print_version "$ARMC6_CC" "--vsn" "armclang not found!" "head -n 2"
-echo
+    : "${ARMC6_CC:=armclang}"
+    print_version "$ARMC6_CC" "--vsn" "armclang not found!" "head -n 2"
+    echo
+fi
 
 print_version "arm-none-eabi-gcc" "--version" "gcc-arm not found!" "head -n 1"
 echo
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 16e19a9..bcd97a0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -81,6 +81,7 @@
 add_test_suite(gcm gcm.aes192_de)
 add_test_suite(gcm gcm.aes256_de)
 add_test_suite(gcm gcm.camellia)
+add_test_suite(hkdf)
 add_test_suite(hmac_drbg hmac_drbg.misc)
 add_test_suite(hmac_drbg hmac_drbg.no_reseed)
 add_test_suite(hmac_drbg hmac_drbg.nopr)
diff --git a/tests/Makefile b/tests/Makefile
index 23baef3..9b9aafe 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -71,6 +71,7 @@
 	test_suite_gcm.aes192_en$(EXEXT)				\
 	test_suite_gcm.aes256_en$(EXEXT)				\
 	test_suite_gcm.camellia$(EXEXT)					\
+	test_suite_hkdf$(EXEXT)						\
 	test_suite_hmac_drbg.misc$(EXEXT)				\
 	test_suite_hmac_drbg.no_reseed$(EXEXT)				\
 	test_suite_hmac_drbg.nopr$(EXEXT)				\
@@ -182,6 +183,10 @@
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_gcm test_suite_gcm.camellia
 
+test_suite_hkdf.c : suites/test_suite_hkdf.function suites/test_suite_hkdf.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo "  Gen   $@"
+	perl scripts/generate_code.pl suites test_suite_hkdf test_suite_hkdf
+
 test_suite_hmac_drbg.misc.c : suites/test_suite_hmac_drbg.function suites/test_suite_hmac_drbg.misc.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_hmac_drbg test_suite_hmac_drbg.misc
@@ -350,6 +355,10 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test_suite_hkdf$(EXEXT): test_suite_hkdf.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test_suite_hmac_drbg.misc$(EXEXT): test_suite_hmac_drbg.misc.c $(DEP)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 497a261..e6c7549 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -94,7 +94,6 @@
 MEMORY=0
 FORCE=0
 KEEP_GOING=0
-RELEASE=0
 RUN_ARMCC=1
 YOTTA=1
 
@@ -126,8 +125,12 @@
   -m|--memory           Additional optional memory tests.
      --armcc            Run ARM Compiler builds (on by default).
      --no-armcc         Skip ARM Compiler builds.
+     --no-force         Refuse to overwrite modified files (default).
+     --no-keep-going    Stop at the first error (default).
+     --no-memory        No additional memory tests (default).
      --no-yotta         Skip yotta module build.
      --out-of-source-dir=<path>  Directory used for CMake out-of-source build tests.
+     --random-seed      Use a random seed value for randomized tests (default).
   -r|--release-test     Run this script in release mode. This fixes the seed value to 1.
   -s|--seed             Integer seed value to use for this test run.
      --yotta            Build yotta module (on by default).
@@ -214,74 +217,29 @@
 
 while [ $# -gt 0 ]; do
     case "$1" in
-        --armcc)
-            RUN_ARMCC=1
-            ;;
-        --armc5-bin-dir)
-            shift
-            ARMC5_BIN_DIR="$1"
-            ;;
-        --armc6-bin-dir)
-            shift
-            ARMC6_BIN_DIR="$1"
-            ;;
-        --force|-f)
-            FORCE=1
-            ;;
-        --gnutls-cli)
-            shift
-            GNUTLS_CLI="$1"
-            ;;
-        --gnutls-legacy-cli)
-            shift
-            GNUTLS_LEGACY_CLI="$1"
-            ;;
-        --gnutls-legacy-serv)
-            shift
-            GNUTLS_LEGACY_SERV="$1"
-            ;;
-        --gnutls-serv)
-            shift
-            GNUTLS_SERV="$1"
-            ;;
-        --help|-h)
-            usage
-            exit
-            ;;
-        --keep-going|-k)
-            KEEP_GOING=1
-            ;;
-        --memory|-m)
-            MEMORY=1
-            ;;
-        --no-armcc)
-            RUN_ARMCC=0
-            ;;
-        --no-yotta)
-            YOTTA=0
-            ;;
-        --openssl)
-            shift
-            OPENSSL="$1"
-            ;;
-        --openssl-legacy)
-            shift
-            OPENSSL_LEGACY="$1"
-            ;;
-        --out-of-source-dir)
-            shift
-            OUT_OF_SOURCE_DIR="$1"
-            ;;
-        --release-test|-r)
-            RELEASE=1
-            ;;
-        --seed|-s)
-            shift
-            SEED="$1"
-            ;;
-        --yotta)
-            YOTTA=1
-            ;;
+        --armcc) RUN_ARMCC=1;;
+        --armc5-bin-dir) shift; ARMC5_BIN_DIR="$1";;
+        --armc6-bin-dir) shift; ARMC6_BIN_DIR="$1";;
+        --force|-f) FORCE=1;;
+        --gnutls-cli) shift; GNUTLS_CLI="$1";;
+        --gnutls-legacy-cli) shift; GNUTLS_LEGACY_CLI="$1";;
+        --gnutls-legacy-serv) shift; GNUTLS_LEGACY_SERV="$1";;
+        --gnutls-serv) shift; GNUTLS_SERV="$1";;
+        --help|-h) usage; exit;;
+        --keep-going|-k) KEEP_GOING=1;;
+        --memory|-m) MEMORY=1;;
+        --no-armcc) RUN_ARMCC=0;;
+        --no-force) FORCE=0;;
+        --no-keep-going) KEEP_GOING=0;;
+        --no-memory) MEMORY=0;;
+        --no-yotta) YOTTA=0;;
+        --openssl) shift; OPENSSL="$1";;
+        --openssl-legacy) shift; OPENSSL_LEGACY="$1";;
+        --out-of-source-dir) shift; OUT_OF_SOURCE_DIR="$1";;
+        --random-seed) unset SEED;;
+        --release-test|-r) SEED=1;;
+        --seed|-s) shift; SEED="$1";;
+        --yotta) YOTTA=1;;
         *)
             echo >&2 "Unknown option: $1"
             echo >&2 "Run $0 --help for usage."
@@ -386,11 +344,6 @@
     fi
 }
 
-if [ $RELEASE -eq 1 ]; then
-    # Fix the seed value to 1 to ensure that the tests are deterministic.
-    SEED=1
-fi
-
 msg "info: $0 configuration"
 echo "MEMORY: $MEMORY"
 echo "FORCE: $FORCE"
@@ -416,12 +369,14 @@
 export GNUTLS_SERV="$GNUTLS_SERV"
 
 # Avoid passing --seed flag in every call to ssl-opt.sh
-[ ! -z ${SEED+set} ] && export SEED
+if [ -n "${SEED-}" ]; then
+  export SEED
+fi
 
 # 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
@@ -447,7 +402,7 @@
 OPENSSL="$OPENSSL" OPENSSL_LEGACY="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_CLI" \
     GNUTLS_SERV="$GNUTLS_SERV" GNUTLS_LEGACY_CLI="$GNUTLS_LEGACY_CLI" \
     GNUTLS_LEGACY_SERV="$GNUTLS_LEGACY_SERV" ARMC5_CC="$ARMC5_CC" \
-    ARMC6_CC="$ARMC6_CC" scripts/output_env.sh
+    ARMC6_CC="$ARMC6_CC" RUN_ARMCC="$RUN_ARMCC" scripts/output_env.sh
 
 msg "test: recursion.pl" # < 1s
 tests/scripts/recursion.pl library/*.c
@@ -907,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/tests/suites/test_suite_hkdf.data b/tests/suites/test_suite_hkdf.data
new file mode 100644
index 0000000..b58ec93
--- /dev/null
+++ b/tests/suites/test_suite_hkdf.data
@@ -0,0 +1,27 @@
+HKDF RFC5869 Test Vector #1
+depends_on:MBEDTLS_SHA256_C
+test_hkdf:6:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
+
+HKDF RFC5869 Test Vector #2
+depends_on:MBEDTLS_SHA256_C
+test_hkdf:6:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"
+
+HKDF RFC5869 Test Vector #3
+depends_on:MBEDTLS_SHA256_C
+test_hkdf:6:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"":"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"
+
+HKDF RFC5869 Test Vector #4
+depends_on:MBEDTLS_SHA1_C
+test_hkdf:4:"0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":"085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896"
+
+HKDF RFC5869 Test Vector #5
+depends_on:MBEDTLS_SHA1_C
+test_hkdf:4:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4"
+
+HKDF RFC5869 Test Vector #6
+depends_on:MBEDTLS_SHA1_C
+test_hkdf:4:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"":"0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918"
+
+HKDF RFC5869 Test Vector #7
+depends_on:MBEDTLS_SHA1_C
+test_hkdf:4:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"":"":"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48"
diff --git a/tests/suites/test_suite_hkdf.function b/tests/suites/test_suite_hkdf.function
new file mode 100644
index 0000000..21a9447
--- /dev/null
+++ b/tests/suites/test_suite_hkdf.function
@@ -0,0 +1,39 @@
+/* BEGIN_HEADER */
+#include "mbedtls/hkdf.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_HKDF_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void test_hkdf(int md_alg, char *hex_ikm_string, char *hex_salt_string,
+               char *hex_info_string, char *hex_okm_string)
+{
+    int ret;
+    size_t ikm_len, salt_len, info_len, okm_len;
+    unsigned char ikm[1024] = {'\0'};
+    unsigned char salt[1024] = {'\0'};
+    unsigned char info[1024] = {'\0'};
+    unsigned char expected_okm[1024] = {'\0'};
+    unsigned char okm[1024] = {'\0'};
+    unsigned char okm_string[1000] = {'\0'};
+
+    const mbedtls_md_info_t *md = mbedtls_md_info_from_type(md_alg);
+    TEST_ASSERT(md != NULL);
+
+    ikm_len = unhexify(ikm, hex_ikm_string);
+    salt_len = unhexify(salt, hex_salt_string);
+    info_len = unhexify(info, hex_info_string);
+    okm_len = unhexify(expected_okm, hex_okm_string);
+
+    ret = mbedtls_hkdf(md, salt, salt_len, ikm, ikm_len, info, info_len, okm,
+                       okm_len);
+    TEST_ASSERT(ret == 0);
+
+    // Run hexify on it so that it looks nicer if the assertion fails
+    hexify(okm_string, okm, okm_len);
+    TEST_ASSERT(!strcmp((char *)okm_string, hex_okm_string));
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index 79cc751..0aca470 100644
--- a/tests/suites/test_suite_version.data
+++ b/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
 Check compiletime library version
-check_compiletime_version:"2.8.0"
+check_compiletime_version:"2.9.0"
 
 Check runtime library version
-check_runtime_version:"2.8.0"
+check_runtime_version:"2.9.0"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":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..4c5c480 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -178,6 +178,7 @@
     <ClInclude Include="..\..\include\mbedtls\error.h" />

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

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

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

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

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

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

@@ -197,6 +198,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" />

@@ -247,6 +249,7 @@
     <ClCompile Include="..\..\library\error.c" />

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

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

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

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

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

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

@@ -266,6 +269,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>