Merge remote-tracking branch 'upstream-public/pr/1629' into evaluation
diff --git a/ChangeLog b/ChangeLog
index 7c23ffc..0133548 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,33 +2,70 @@
 
 = 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.
+Features
+   * Add new crypto primitives from RFC 7539: stream cipher Chacha20, one-time
+   authenticator Poly1305 and AEAD construct Chacha20-Poly1305. Contributed by
+   Daniel King (#485).
+
+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.
+   * 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 (#348).
+     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.
@@ -36,15 +73,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
@@ -52,26 +90,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.
@@ -82,7 +126,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
@@ -95,8 +139,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
@@ -295,7 +344,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
@@ -489,8 +538,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 3c5b133..65ab229 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,22 @@
 }
 mbedtls_aes_context;
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief The AES XTS context-type definition.
+ */
+typedef struct
+{
+    mbedtls_aes_context crypt; /*!< The AES context to use for AES block
+                                        encryption or decryption. */
+    mbedtls_aes_context tweak; /*!< The AES context used for tweak computation. */
+} mbedtls_aes_xts_context;
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+#else  /* MBEDTLS_AES_ALT */
+#include "aes_alt.h"
+#endif /* MBEDTLS_AES_ALT */
+
 /**
  * \brief          This function initializes the specified AES context.
  *
@@ -105,6 +121,25 @@
  */
 void mbedtls_aes_free( mbedtls_aes_context *ctx );
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief          This function initializes the specified AES XTS context.
+ *
+ *                 It must be the first API called before using
+ *                 the context.
+ *
+ * \param ctx      The AES XTS context to initialize.
+ */
+void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx );
+
+/**
+ * \brief          This function releases and clears the specified AES XTS context.
+ *
+ * \param ctx      The AES XTS context to clear.
+ */
+void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 /**
  * \brief          This function sets the encryption key.
  *
@@ -137,6 +172,44 @@
 int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
                     unsigned int keybits );
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief          This function sets the encryption key.
+ *
+ * \param ctx      The AES XTS context to which the key should be bound.
+ * \param key      The encryption key. This is comprised of the XTS key1
+ *                 concatenated with the XTS key2.
+ * \param keybits  The size of data passed in bits. Valid options are:
+ *                 <ul><li>256 bits</li>
+ *                 <li>384 bits</li>
+ *                 <li>512 bits</li></ul>
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits );
+
+/**
+ * \brief          This function sets the decryption key.
+ *
+ * \param ctx      The AES XTS context to which the key should be bound.
+ * \param key      The decryption key. This is comprised of the XTS key1
+ *                 concatenated with the XTS key2.
+ * \param keybits  The size of data passed. Valid options are:
+ *                 <ul><li>256 bits</li>
+ *                 <li>384 bits</li>
+ *                 <li>512 bits</li></ul>
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
+ */
+int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 /**
  * \brief          This function performs an AES single-block encryption or
  *                 decryption operation.
@@ -291,6 +364,46 @@
                     unsigned char *output );
 #endif /*MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/**
+ * \brief This function performs an AES-OFB (Output Feedback Mode) encryption
+ *        or decryption operation.
+ *
+ *        For OFB, you must set up the context with mbedtls_aes_setkey_enc(),
+ *        regardless of whether you are performing an encryption or decryption
+ *        operation. This is because OFB mode uses the same key schedule for
+ *        encryption and decryption.
+ *
+ *        The OFB operation is identical for encryption or decryption, therefore
+ *        no operation mode needs to be specified.
+ *
+ * \note  Upon exit, the content of the IV is updated so that you can
+ *        call the same function again on the next
+ *        block(s) of data and get the same result as if it was
+ *        encrypted in one call. This allows a "streaming" usage.
+ *        If you need to retain the contents of the
+ *        IV, you must either save it manually or use the cipher
+ *        module instead.
+ *
+ *
+ * \param ctx      The AES context to use for encryption or decryption.
+ * \param length   The length of the input data.
+ * \param iv_off   The offset in IV (updated after use).
+ * \param iv       The initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 /**
  * \brief      This function performs an AES-CTR encryption or decryption
@@ -329,6 +442,44 @@
                        unsigned char *output );
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/**
+ * \brief      This function performs an AES-XTS encryption or decryption
+ *             operation for an entire XTS sector.
+ *
+ *             AES-XTS encrypts or decrypts blocks based on their location as
+ *             defined by a sector number. These must be provided by \p sector.
+ *
+ *             NIST SP 800-38E limits the maximum size of a data unit to 2**20
+ *             AES blocks. If the data unit is larger than this, this function
+ *             returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH.
+ *
+ * \param ctx          The AES XTS context to use for AES XTS operations.
+ * \param mode         The AES operation: #MBEDTLS_AES_ENCRYPT or
+ *                     #MBEDTLS_AES_DECRYPT.
+ * \param length       The length of both an entire sector and the input data
+ *                     in bytes. The length must be at least 16 bytes. The
+ *                     length does not need to be a multiple of 16 bytes.
+ * \param data_unit    The data unit (commonly a block device sector) address
+ *                     in byte array form. The least significant byte must be
+ *                     at sector[0]. The most significant byte must be at
+ *                     sector[15]. Array must be 16 bytes in length.
+ * \param input        The buffer holding the input data.
+ * \param output       The buffer holding the output data.
+ *
+ * \return             \c 0 on success.
+ * \return             #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if length smaller
+ *                     than an AES block in size (16 bytes) or if the length is
+ *                     larger than 2**20 blocks.
+ */
+int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
+                           int mode,
+                           size_t length,
+                           const unsigned char data_unit[16],
+                           const unsigned char *input,
+                           unsigned char *output );
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 /**
  * \brief           Internal AES block encryption function. This is only
  *                  exposed to allow overriding it using
@@ -396,18 +547,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 7d117d9..1bc79d8 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           The CCM* callback for encrypting with variable tag length.
  *                  The function pointer is passed to the APIs called. This
@@ -347,17 +352,6 @@
                       mbedtls_ccm_star_get_tag_len_t get_tag_len,
                       void *get_tlen_ctx );
 
-#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/chacha20.h b/include/mbedtls/chacha20.h
new file mode 100644
index 0000000..7a8cd53
--- /dev/null
+++ b/include/mbedtls/chacha20.h
@@ -0,0 +1,210 @@
+/**
+ * \file chacha20.h
+ *
+ * \brief   This file contains ChaCha20 definitions and functions.
+ *
+ *          ChaCha20 is a stream cipher that can encrypt and decrypt
+ *          information. ChaCha was created by Daniel Bernstein as a variant of
+ *          its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf
+ *          ChaCha20 is the variant with 20 rounds, that was also standardized
+ *          in RFC 7539.
+ *
+ * \author Daniel King <damaki.gh@gmail.com>
+ */
+
+/*  Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_CHACHA20_H
+#define MBEDTLS_CHACHA20_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA         -0x0053 /**< Invalid input parameter(s). */
+#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE    -0x0055 /**< Feature not available. For example, s part of the API is not implemented. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDTLS_CHACHA20_ALT)
+
+typedef struct
+{
+    uint32_t initial_state[16];  /*! The initial state (before round operations). */
+    uint32_t working_state[16];  /*! The working state (after round operations). */
+    uint8_t  keystream8[64];     /*! Leftover keystream bytes. */
+    size_t keystream_bytes_used; /*! Number of keystream bytes already used. */
+}
+mbedtls_chacha20_context;
+
+#else  /* MBEDTLS_CHACHA20_ALT */
+#include "chacha20_alt.h"
+#endif /* MBEDTLS_CHACHA20_ALT */
+
+/**
+ * \brief           This function initializes the specified ChaCha20 context.
+ *
+ *                  It must be the first API called before using
+ *                  the context.
+ *
+ *                  It is usually followed by calls to
+ *                  \c mbedtls_chacha20_setkey() and
+ *                  \c mbedtls_chacha20_starts(), then one or more calls to
+ *                  to \c mbedtls_chacha20_update(), and finally to
+ *                  \c mbedtls_chacha20_free().
+ *
+ * \param ctx       The ChaCha20 context to initialize.
+ */
+void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx );
+
+/**
+ * \brief           This function releases and clears the specified ChaCha20 context.
+ *
+ * \param ctx       The ChaCha20 context to clear.
+ */
+void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx );
+
+/**
+ * \brief           This function sets the encryption/decryption key.
+ *
+ * \note            After using this function, you must also call
+ *                  \c mbedtls_chacha20_starts() to set a nonce before you
+ *                  start encrypting/decrypting data with
+ *                  \c mbedtls_chacha_update().
+ *
+ * \param ctx       The ChaCha20 context to which the key should be bound.
+ * \param key       The encryption/decryption key. Must be 32 bytes in length.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL.
+ */
+int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
+                             const unsigned char key[32] );
+
+/**
+ * \brief           This function sets the nonce and initial counter value.
+ *
+ * \note            A ChaCha20 context can be re-used with the same key by
+ *                  calling this function to change the nonce.
+ *
+ * \warning         You must never use the same nonce twice with the same key.
+ *                  This would void any confidentiality guarantees for the
+ *                  messages encrypted with the same nonce and key.
+ *
+ * \param ctx       The ChaCha20 context to which the nonce should be bound.
+ * \param nonce     The nonce. Must be 12 bytes in size.
+ * \param counter   The initial counter value. This is usually 0.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is
+ *                  NULL.
+ */
+int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
+                             const unsigned char nonce[12],
+                             uint32_t counter );
+
+/**
+ * \brief           This function encrypts or decrypts data.
+ *
+ *                  Since ChaCha20 is a stream cipher, the same operation is
+ *                  used for encrypting and decrypting data.
+ *
+ * \note            The \p input and \p output pointers must either be equal or
+ *                  point to non-overlapping buffers.
+ *
+ * \note            \c mbedtls_chacha20_setkey() and
+ *                  \c mbedtls_chacha20_starts() must be called at least once
+ *                  to setup the context before this function can be called.
+ *
+ * \note            This function can be called mutliple times in a row in
+ *                  order to encrypt of decrypt data piecewise with the same
+ *                  key and nonce.
+ *
+ * \param ctx       The ChaCha20 context to use for encryption or decryption.
+ * \param size      The length of the input data in bytes.
+ * \param input     The buffer holding the input data.
+ *                  This pointer can be NULL if size == 0.
+ * \param output    The buffer holding the output data.
+ *                  Must be able to hold \p size bytes.
+ *                  This pointer can be NULL if size == 0.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if the ctx, input, or
+ *                  output pointers are NULL.
+ */
+int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
+                             size_t size,
+                             const unsigned char *input,
+                             unsigned char *output );
+
+/**
+ * \brief           This function encrypts or decrypts data with ChaCha20 and
+ *                  the given key and nonce.
+ *
+ *                  Since ChaCha20 is a stream cipher, the same operation is
+ *                  used for encrypting and decrypting data.
+ *
+ * \warning         You must never use the same (key, nonce) pair more than
+ *                  once. This would void any confidentiality guarantees for
+ *                  the messages encrypted with the same nonce and key.
+ *
+ * \note            The \p input and \p output pointers must either be equal or
+ *                  point to non-overlapping buffers.
+ *
+ * \param key       The encryption/decryption key. Must be 32 bytes in length.
+ * \param nonce     The nonce. Must be 12 bytes in size.
+ * \param counter   The initial counter value. This is usually 0.
+ * \param size      The length of the input data in bytes.
+ * \param input     The buffer holding the input data.
+ *                  This pointer can be NULL if size == 0.
+ * \param output    The buffer holding the output data.
+ *                  Must be able to hold \p size bytes.
+ *                  This pointer can be NULL if size == 0.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if key, nonce, input,
+ *                  or output is NULL.
+ */
+int mbedtls_chacha20_crypt( const unsigned char key[32],
+                            const unsigned char nonce[12],
+                            uint32_t counter,
+                            size_t size,
+                            const unsigned char* input,
+                            unsigned char* output );
+
+/**
+ * \brief           The ChaCha20 checkup routine.
+ *
+ * \return          \c 0 on success.
+ * \return          \c 1 on failure.
+ */
+int mbedtls_chacha20_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CHACHA20_H */
diff --git a/include/mbedtls/chachapoly.h b/include/mbedtls/chachapoly.h
new file mode 100644
index 0000000..a55a3ee
--- /dev/null
+++ b/include/mbedtls/chachapoly.h
@@ -0,0 +1,327 @@
+/**
+ * \file chachapoly.h
+ *
+ * \brief   This file contains the AEAD-ChaCha20-Poly1305 definitions and
+ *          functions.
+ *
+ *          ChaCha20-Poly1305 is an algorithm for Authenticated Encryption
+ *          with Associated Data (AEAD) that can be used to encrypt and
+ *          authenticate data. It is based on ChaCha20 and Poly1305 by Daniel
+ *          Bernstein and was standardized in RFC 7539.
+ *
+ * \author Daniel King <damaki.gh@gmail.com>
+ */
+
+/*  Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_CHACHAPOLY_H
+#define MBEDTLS_CHACHAPOLY_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#define MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA       -0x0054 /**< Invalid input parameter(s). */
+#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE            -0x0056 /**< The requested operation is not permitted in the current state. */
+#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED          -0x0058 /**< Authenticated decryption failed: data was not authentic. */
+#define MBEDTLS_ERR_CHACHAPOLY_FEATURE_UNAVAILABLE  -0x005A /**< Feature not available. For example, s part of the API is not implemented. */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+    MBEDTLS_CHACHAPOLY_ENCRYPT,     /**< The mode value for performing encryption. */
+    MBEDTLS_CHACHAPOLY_DECRYPT      /**< The mode value for performing decryption. */
+}
+mbedtls_chachapoly_mode_t;
+
+#if !defined(MBEDTLS_CHACHAPOLY_ALT)
+
+#include "chacha20.h"
+#include "poly1305.h"
+
+typedef struct
+{
+    mbedtls_chacha20_context chacha20_ctx;  /**< The ChaCha20 context. */
+    mbedtls_poly1305_context poly1305_ctx;  /**< The Poly1305 context. */
+    uint64_t aad_len;                       /**< The length (bytes) of the Additional Authenticated Data. */
+    uint64_t ciphertext_len;                /**< The length (bytes) of the ciphertext. */
+    int state;                              /**< The current state of the context. */
+    mbedtls_chachapoly_mode_t mode;         /**< Cipher mode (encrypt or decrypt). */
+}
+mbedtls_chachapoly_context;
+
+#else /* !MBEDTLS_CHACHAPOLY_ALT */
+#include "chachapoly_alt.h"
+#endif /* !MBEDTLS_CHACHAPOLY_ALT */
+
+/**
+ * \brief           This function initializes the specified ChaCha20-Poly1305 context.
+ *
+ *                  It must be the first API called before using
+ *                  the context. It must be followed by a call to
+ *                  \c mbedtls_chachapoly_setkey() before any operation can be
+ *                  done, and to \c mbedtls_chachapoly_free() once all
+ *                  operations with that context have been finished.
+ *
+ *                  In order to encrypt or decrypt full messages at once, for
+ *                  each message you should make a single call to
+ *                  \c mbedtls_chachapoly_crypt_and_tag() or
+ *                  \c mbedtls_chachapoly_auth_decrypt().
+ *
+ *                  In order to encrypt or decrypt messages piecewise, for each
+ *                  message you should make a call to
+ *                  \c mbedtls_chachapoly_starts(), then 0 or more calls to
+ *                  \c mbedtls_chachapoly_update_aad(), then 0 or more calls to
+ *                  \c mbedtls_chachapoly_update(), then one call to
+ *                  \c mbedtls_chachapoly_finish().
+ *
+ *
+ * \param ctx       The ChachaPoly context to initialize.
+ */
+void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx );
+
+/**
+ * \brief           This function releases and clears the specified ChaCha20-Poly1305 context.
+ *
+ * \param ctx       The ChachaPoly context to clear.
+ */
+void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx );
+
+/**
+ * \brief           This function sets the ChaCha20-Poly1305 symmetric encryption key.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context to which the key should be
+ *                  bound.
+ * \param key       The 256-bit (32 bytes) key.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA
+ *                  if \p ctx or \p key are NULL.
+ */
+int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
+                               const unsigned char key[32] );
+
+/**
+ * \brief           This function starts a ChaCha20-Poly1305 encryption or
+ *                  decryption operation.
+ *
+ * \warning         You must never use the same nonce twice with the same key.
+ *                  This would void any confidentiality and authenticity
+ *                  guarantees for the messages encrypted with the same nonce
+ *                  and key.
+ *
+ * \note            If the context is being used for AAD only (no data to
+ *                  encrypt or decrypt) then \p mode can be set to any value.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context.
+ * \param nonce     The nonce/IV to use for the message. Must be 12 bytes.
+ * \param mode      The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
+ *                  #MBEDTLS_CHACHAPOLY_DECRYPT.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA
+ *                  if \p ctx or \p mac are NULL.
+ */
+int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
+                               const unsigned char nonce[12],
+                               mbedtls_chachapoly_mode_t mode );
+
+/**
+ * \brief           This function feeds additional data to be authenticated
+ *                  into an ongoing ChaCha20-Poly1305 operation.
+ *
+ *                  The Additional Authenticated Data (AAD), also called
+ *                  Associated Data (AD) is only authenticated but not
+ *                  encrypted nor included in the encrypted output. It is
+ *                  usually transmitted separately fro mthe ciphertext or
+ *                  computed locally by each party.
+ *
+ * \note            This function is called before data is encrypted/decrypted.
+ *                  I.e. call this function to process the AAD before calling
+ *                  \c mbedtls_chachapoly_update().
+ *
+ *                  You may call this function multiple times to process
+ *                  an arbitrary amount of AAD. It is permitted to call
+ *                  this function 0 times, if no AAD is used.
+ *
+ *                  This function cannot be called any more if data has
+ *                  been processed by \c mbedtls_chachapoly_update(),
+ *                  or if the context has been finished.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context to use.
+ * \param aad_len   The length (in bytes) of the AAD. The length has no
+ *                  restrictions.
+ * \param aad       Buffer containing the AAD.
+ *                  This pointer can be NULL if aad_len == 0.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA
+ *                  if \p ctx or \p aad are NULL.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
+ *                  if the operations has not been started or has been
+ *                  finished, or if the AAD has been finished.
+ */
+int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
+                                   const unsigned char *aad,
+                                   size_t aad_len );
+
+/**
+ * \brief           Thus function feeds data to be encrypted or decrypted
+ *                  into an on-going ChaCha20-Poly1305
+ *                  operation.
+ *
+ *                  The direction (encryption or decryption) depends on the
+ *                  mode that was given when calling
+ *                  \c mbedtls_chachapoly_starts().
+ *
+ *                  You may call this function multiple times to process
+ *                  an arbitrary amount of data. It is permitted to call
+ *                  this function 0 times, if no data is to be encrypted
+ *                  or decrypted.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context to use.
+ * \param len       The length (in bytes) of the data to encrypt or decrypt.
+ * \param input     The buffer containing the data to encrypt or decrypt.
+ *                  This pointer can be NULL if len == 0.
+ * \param output    The buffer to where the encrypted or decrypted data is written.
+ *                  Must be able to hold \p len bytes.
+ *                  This pointer can be NULL if len == 0.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA
+ *                  if \p ctx, \p input, or \p output are NULL.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
+ *                  if the operation has not been started or has been
+ *                  finished.
+ */
+int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
+                               size_t len,
+                               const unsigned char *input,
+                               unsigned char *output );
+
+/**
+ * \brief           This function finished the ChaCha20-Poly1305 operation and
+ *                  generates the MAC (authentication tag).
+ *
+ * \param ctx       The ChaCha20-Poly1305 context to use.
+ * \param mac       The buffer to where the 128-bit (16 bytes) MAC is written.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA
+ *                  if \p ctx or \p mac are NULL.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
+ *                  if the operation has not been started or has been
+ *                  finished.
+ */
+int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
+                               unsigned char mac[16] );
+
+/**
+ * \brief           This function performs a complete ChaCha20-Poly1305
+ *                  operation with the previously-set key.
+ *
+ * \note            Before using this function, you must set the key with
+ *                  \c mbedtls_chachapoly_setkey().
+ *
+ * \warning         You must never use the same nonce twice with the same key.
+ *                  This would void any confidentiality and authenticity
+ *                  guarantees for the messages encrypted with the same nonce
+ *                  and key.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context to use (holds the key).
+ * \param mode      The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
+ *                  #MBEDTLS_CHACHAPOLY_DECRYPT.
+ * \param length    The length (in bytes) of the data to encrypt or decrypt.
+ * \param nonce     The 96-bit (12 bytes) nonce/IV to use.
+ * \param aad       The buffer containing the additional authenticated data (AAD).
+ *                  This pointer can be NULL if aad_len == 0.
+ * \param aad_len   The length (in bytes) of the AAD data to process.
+ * \param input     The buffer containing the data to encrypt or decrypt.
+ *                  This pointer can be NULL if ilen == 0.
+ * \param output    The buffer to where the encrypted or decrypted data is written.
+ *                  This pointer can be NULL if ilen == 0.
+ * \param tag       The buffer to where the computed 128-bit (16 bytes) MAC is written.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA
+ *                  if one or more of the required parameters are NULL.
+ */
+int mbedtls_chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
+                                      mbedtls_chachapoly_mode_t mode,
+                                      size_t length,
+                                      const unsigned char nonce[12],
+                                      const unsigned char *aad,
+                                      size_t aad_len,
+                                      const unsigned char *input,
+                                      unsigned char *output,
+                                      unsigned char tag[16] );
+
+/**
+ * \brief           This function performs a complete ChaCha20-Poly1305
+ *                  authenticated decryption with the previously-set key.
+ *
+ * \note            Before using this function, you must set the key with
+ *                  \c mbedtls_chachapoly_setkey().
+ *
+ * \param ctx       The ChaCha20-Poly1305 context to use (holds the key).
+ * \param length    The length (in bytes) of the data to decrypt.
+ * \param nonce     The 96-bit (12 bytes) nonce/IV to use.
+ * \param aad       The buffer containing the additional authenticated data (AAD).
+ *                  This pointer can be NULL if aad_len == 0.
+ * \param aad_len   The length (in bytes) of the AAD data to process.
+ * \param tag       The buffer holding the authentication tag.
+ * \param input     The buffer containing the data to decrypt.
+ *                  This pointer can be NULL if ilen == 0.
+ * \param output    The buffer to where the decrypted data is written.
+ *                  This pointer can be NULL if ilen == 0.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA
+ *                  if one or more of the required parameters are NULL.
+ * \return          #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED
+ *                  if the data was not authentic.
+ */
+int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
+                                     size_t length,
+                                     const unsigned char nonce[12],
+                                     const unsigned char *aad,
+                                     size_t aad_len,
+                                     const unsigned char tag[16],
+                                     const unsigned char *input,
+                                     unsigned char *output );
+
+/**
+ * \brief           The ChaCha20-Poly1305 checkup routine.
+ *
+ * \return          \c 0 on success.
+ * \return          \c 1 on failure.
+ */
+int mbedtls_chachapoly_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CHACHAPOLY_H */
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/cipher.h b/include/mbedtls/cipher.h
index 3ee2ab7..1961b4f 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -37,7 +37,7 @@
 
 #include <stddef.h>
 
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
 #define MBEDTLS_CIPHER_MODE_AEAD
 #endif
 
@@ -86,6 +86,7 @@
     MBEDTLS_CIPHER_ID_CAMELLIA,  /**< The Camellia cipher. */
     MBEDTLS_CIPHER_ID_BLOWFISH,  /**< The Blowfish cipher. */
     MBEDTLS_CIPHER_ID_ARC4,      /**< The RC4 cipher. */
+    MBEDTLS_CIPHER_ID_CHACHA20,  /**< The ChaCha20 cipher. */
 } mbedtls_cipher_id_t;
 
 /**
@@ -145,6 +146,13 @@
     MBEDTLS_CIPHER_CAMELLIA_128_CCM,     /**< Camellia cipher with 128-bit CCM mode. */
     MBEDTLS_CIPHER_CAMELLIA_192_CCM,     /**< Camellia cipher with 192-bit CCM mode. */
     MBEDTLS_CIPHER_CAMELLIA_256_CCM,     /**< Camellia cipher with 256-bit CCM mode. */
+    MBEDTLS_CIPHER_AES_128_OFB,          /**< AES 128-bit cipher in OFB mode. */
+    MBEDTLS_CIPHER_AES_192_OFB,          /**< AES 192-bit cipher in OFB mode. */
+    MBEDTLS_CIPHER_AES_256_OFB,          /**< AES 256-bit cipher in OFB mode. */
+    MBEDTLS_CIPHER_AES_128_XTS,          /**< AES 128-bit cipher in XTS block mode. */
+    MBEDTLS_CIPHER_AES_256_XTS,          /**< AES 256-bit cipher in XTS block mode. */
+    MBEDTLS_CIPHER_CHACHA20,             /**< ChaCha20 stream cipher. */
+    MBEDTLS_CIPHER_CHACHA20_POLY1305,    /**< ChaCha20-Poly1305 AEAD cipher. */
 } mbedtls_cipher_type_t;
 
 /** Supported cipher modes. */
@@ -153,11 +161,12 @@
     MBEDTLS_MODE_ECB,                    /**< The ECB cipher mode. */
     MBEDTLS_MODE_CBC,                    /**< The CBC cipher mode. */
     MBEDTLS_MODE_CFB,                    /**< The CFB cipher mode. */
-    MBEDTLS_MODE_OFB,                    /**< The OFB cipher mode - unsupported. */
+    MBEDTLS_MODE_OFB,                    /**< The OFB cipher mode. */
     MBEDTLS_MODE_CTR,                    /**< The CTR cipher mode. */
     MBEDTLS_MODE_GCM,                    /**< The GCM cipher mode. */
     MBEDTLS_MODE_STREAM,                 /**< The stream cipher mode. */
     MBEDTLS_MODE_CCM,                    /**< The CCM cipher mode. */
+    MBEDTLS_MODE_XTS,                    /**< The XTS cipher mode. */
 } mbedtls_cipher_mode_t;
 
 /** Supported cipher padding types. */
@@ -273,7 +282,8 @@
     /** Number of Bytes that have not been processed yet. */
     size_t unprocessed_len;
 
-    /** Current IV or NONCE_COUNTER for CTR-mode. */
+    /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number
+     * for XTS-mode. */
     unsigned char iv[MBEDTLS_MAX_IV_LENGTH];
 
     /** IV size in Bytes, for ciphers with variable-length IVs. */
@@ -560,11 +570,11 @@
  */
 int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
 /**
  * \brief               This function adds additional data for AEAD ciphers.
- *                      Only supported with GCM. Must be called
- *                      exactly once, after mbedtls_cipher_reset().
+ *                      Currently supported with GCM and ChaCha20+Poly1305.
+ *                      Must be called exactly once, after mbedtls_cipher_reset().
  *
  * \param ctx           The generic cipher context.
  * \param ad            The additional data to use.
@@ -575,7 +585,7 @@
  */
 int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
                       const unsigned char *ad, size_t ad_len );
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
 
 /**
  * \brief               The generic cipher update function. It encrypts or
@@ -633,10 +643,10 @@
 int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
                    unsigned char *output, size_t *olen );
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
 /**
  * \brief               This function writes a tag for AEAD ciphers.
- *                      Only supported with GCM.
+ *                      Currently supported with GCM and ChaCha20+Poly1305.
  *                      Must be called after mbedtls_cipher_finish().
  *
  * \param ctx           The generic cipher context.
@@ -651,7 +661,7 @@
 
 /**
  * \brief               This function checks the tag for AEAD ciphers.
- *                      Only supported with GCM.
+ *                      Currently supported with GCM and ChaCha20+Poly1305.
  *                      Must be called after mbedtls_cipher_finish().
  *
  * \param ctx           The generic cipher context.
@@ -663,7 +673,7 @@
  */
 int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
                       const unsigned char *tag, size_t tag_len );
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
 
 /**
  * \brief               The generic all-in-one encryption/decryption function,
diff --git a/include/mbedtls/cipher_internal.h b/include/mbedtls/cipher_internal.h
index 969ff9c..95b7ef7 100644
--- a/include/mbedtls/cipher_internal.h
+++ b/include/mbedtls/cipher_internal.h
@@ -59,11 +59,20 @@
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     /** Encrypt using CFB (Full length) */
+
     int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off,
                      unsigned char *iv, const unsigned char *input,
                      unsigned char *output );
 #endif
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    /** Encrypt using OFB (Full length) */
+    int (*ofb_func)( void *ctx, size_t length, size_t *iv_off,
+                     unsigned char *iv,
+                     const unsigned char *input,
+                     unsigned char *output );
+#endif
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     /** Encrypt using CTR */
     int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
@@ -71,6 +80,13 @@
                      const unsigned char *input, unsigned char *output );
 #endif
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    /** Encrypt using XTS */
+    int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length,
+                     const unsigned char data_unit[16],
+                     const unsigned char *input, unsigned char *output );
+#endif
+
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     /** Encrypt using STREAM */
     int (*stream_func)( void *ctx, size_t length,
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 9585e69..8baf439 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
@@ -269,11 +269,13 @@
  *            digests and ciphers instead.
  *
  */
+//#define MBEDTLS_CHACHAPOLY_ALT
 //#define MBEDTLS_AES_ALT
 //#define MBEDTLS_ARC4_ALT
 //#define MBEDTLS_BLOWFISH_ALT
 //#define MBEDTLS_CAMELLIA_ALT
 //#define MBEDTLS_CCM_ALT
+//#define MBEDTLS_CHACHA20_ALT
 //#define MBEDTLS_CMAC_ALT
 //#define MBEDTLS_DES_ALT
 //#define MBEDTLS_DHM_ALT
@@ -282,6 +284,7 @@
 //#define MBEDTLS_MD2_ALT
 //#define MBEDTLS_MD4_ALT
 //#define MBEDTLS_MD5_ALT
+//#define MBEDTLS_POLY1305_ALT
 //#define MBEDTLS_RIPEMD160_ALT
 //#define MBEDTLS_RSA_ALT
 //#define MBEDTLS_SHA1_ALT
@@ -496,6 +499,13 @@
 #define MBEDTLS_CIPHER_MODE_CBC
 
 /**
+ * \def MBEDTLS_CIPHER_MODE_OFB
+ *
+ * Enable Output Feedback mode (OFB) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_OFB
+
+/**
  * \def MBEDTLS_CIPHER_MODE_CFB
  *
  * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
@@ -510,6 +520,14 @@
 #define MBEDTLS_CIPHER_MODE_CTR
 
 /**
+ * \def MBEDTLS_CIPHER_MODE_XTS
+ *
+ * Enable XEX-based tweaked-codebook mode with ciphertext stealing mode (XTS)
+ * for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_XTS
+
+/**
  * \def MBEDTLS_CIPHER_NULL_CIPHER
  *
  * Enable NULL cipher.
@@ -1687,6 +1705,17 @@
 #define MBEDTLS_AES_C
 
 /**
+ * \def MBEDTLS_CHACHAPOLY_C
+ *
+ * Enable the ChaCha20-Poly1305 AEAD algorithm.
+ *
+ * Module:  library/chachapoly.c
+ *
+ * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
+ */
+#define MBEDTLS_CHACHAPOLY_C
+
+/**
  * \def MBEDTLS_ARC4_C
  *
  * Enable the ARCFOUR stream cipher.
@@ -1836,6 +1865,16 @@
 #define MBEDTLS_CAMELLIA_C
 
 /**
+ * \def MBEDTLS_CHACHA20_C
+ *
+ * Enable the ChaCha20 block cipher.
+ *
+ * Module:  library/chacha20.c
+ * Caller:  library/chachapoly.c
+ */
+#define MBEDTLS_CHACHA20_C
+
+/**
  * \def MBEDTLS_CCM_C
  *
  * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
@@ -1862,6 +1901,15 @@
 #define MBEDTLS_CERTS_C
 
 /**
+ * \def MBEDTLS_CHACHA20_C
+ *
+ * Enable the ChaCha20 stream cipher.
+ *
+ * Module:  library/chacha20.c
+ */
+#define MBEDTLS_CHACHA20_C
+
+/**
  * \def MBEDTLS_CIPHER_C
  *
  * Enable the generic cipher layer.
@@ -2092,6 +2140,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.
@@ -2389,6 +2452,16 @@
 #define MBEDTLS_PLATFORM_C
 
 /**
+ * \def MBEDTLS_POLY1305_C
+ *
+ * Enable the Poly1305 MAC algorithm.
+ *
+ * Module:  library/poly1305.c
+ * Caller:  library/chachapoly.c
+ */
+#define MBEDTLS_POLY1305_C
+
+/**
  * \def MBEDTLS_RIPEMD160_C
  *
  * Enable the RIPEMD-160 hash algorithm.
@@ -2852,6 +2925,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..5290721 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
@@ -76,6 +76,9 @@
  * SHA1      1                  0x0035-0x0035
  * SHA256    1                  0x0037-0x0037
  * SHA512    1                  0x0039-0x0039
+ * CHACHA20  2                  0x0053-0x0055
+ * POLY1305  2                  0x0057-0x0059
+ * CHACHAPOLY 4 0x0054-0x005A
  *
  * High-level module nr (3 bits - 0x0...-0x7...)
  * Name      ID  Nr of Errors
@@ -88,6 +91,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/poly1305.h b/include/mbedtls/poly1305.h
new file mode 100644
index 0000000..021a3a0
--- /dev/null
+++ b/include/mbedtls/poly1305.h
@@ -0,0 +1,178 @@
+/**
+ * \file poly1305.h
+ *
+ * \brief   This file containts Poly1305 definitions and functions.
+ *
+ *          Poly1305 is a one-time message authenticator that can be used to
+ *          authenticate messages. Poly1305-AES was created by Daniel
+ *          Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic
+ *          Poly1305 algorithm (not tied to AES) was also standardized in RFC
+ *          7539.
+ *
+ * \author Daniel King <damaki.gh@gmail.com>
+ */
+
+/*  Copyright (C) 2006-2018, Arm Limited (or its affiliates), 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_POLY1305_H
+#define MBEDTLS_POLY1305_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA         -0x0057 /**< Invalid input parameter(s). */
+#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE    -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDTLS_POLY1305_ALT)
+
+typedef struct
+{
+    uint32_t r[4];      /** The value for 'r' (low 128 bits of the key). */
+    uint32_t s[4];      /** The value for 's' (high 128 bits of the key). */
+    uint32_t acc[5];    /** The accumulator number. */
+    uint8_t queue[16];  /** The current partial block of data. */
+    size_t queue_len;   /** The number of bytes stored in 'queue'. */
+}
+mbedtls_poly1305_context;
+
+#else  /* MBEDTLS_POLY1305_ALT */
+#include "poly1305_alt.h"
+#endif /* MBEDTLS_POLY1305_ALT */
+
+/**
+ * \brief           This function initializes the specified Poly1305 context.
+ *
+ *                  It must be the first API called before using
+ *                  the context.
+ *
+ *                  It is usually followed by a call to
+ *                  \c mbedtls_poly1305_starts(), then one or more calls to
+ *                  \c mbedtls_poly1305_update(), then one call to
+ *                  \c mbedtls_poly1305_finish(), then finally
+ *                  \c mbedtls_poly1305_free().
+ *
+ * \param ctx       The Poly1305 context to initialize.
+ */
+void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx );
+
+/**
+ * \brief           This function releases and clears the specified Poly1305 context.
+ *
+ * \param ctx       The Poly1305 context to clear.
+ */
+void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx );
+
+/**
+ * \brief           This function sets the one-time authentication key.
+ *
+ * \warning         The key must be unique and unpredictable for each
+ *                  invocation of Poly1305.
+ *
+ * \param ctx       The Poly1305 context to which the key should be bound.
+ * \param key       The buffer containing the 256-bit key.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ *                  if ctx or key are NULL.
+ */
+int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
+                             const unsigned char key[32] );
+
+/**
+ * \brief           This functions feeds an input bufer into an ongoing
+ *                  Poly1305 computation.
+ *
+ *                  It is called between \c mbedtls_cipher_cmac_starts() and
+ *                  \c mbedtls_cipher_cmac_finish().
+ *                  Can be called repeatedly to process a stream of data.
+ *
+ * \param ctx       The Poly1305 context to use for the Poly1305 operation.
+ * \param ilen      The length of the input data (in bytes). Any value is accepted.
+ * \param input     The buffer holding the input data.
+ *                  This pointer can be NULL if ilen == 0.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ *                  if ctx or input are NULL.
+ */
+int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
+                             const unsigned char *input,
+                             size_t ilen );
+
+/**
+ * \brief           This function generates the Poly1305 Message
+ *                  Authentication Code (MAC).
+ *
+ * \param ctx       The Poly1305 context to use for the Poly1305 operation.
+ * \param mac       The buffer to where the MAC is written. Must be big enough
+ *                  to hold the 16-byte MAC.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ *                  if ctx or mac are NULL.
+ */
+int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
+                             unsigned char mac[16] );
+
+/**
+ * \brief           This function calculates the Poly1305 MAC of the input
+ *                  buffer with the provided key.
+ *
+ * \warning         The key must be unique and unpredictable for each
+ *                  invocation of Poly1305.
+ *
+ * \param key       The buffer containing the 256-bit key.
+ * \param ilen      The length of the input data (in bytes). Any value is accepted.
+ * \param input     The buffer holding the input data.
+ *                  This pointer can be NULL if ilen == 0.
+ * \param mac       The buffer to where the MAC is written. Must be big enough
+ *                  to hold the 16-byte MAC.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
+ *                  if key, input, or mac are NULL.
+ */
+int mbedtls_poly1305_mac( const unsigned char key[32],
+                          const unsigned char *input,
+                          size_t ilen,
+                          unsigned char mac[16] );
+
+/**
+ * \brief           The Poly1305 checkup routine.
+ *
+ * \return          \c 0 on success.
+ * \return          \c 1 on failure.
+ */
+int mbedtls_poly1305_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_POLY1305_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..4ac9854 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -13,6 +13,8 @@
     blowfish.c
     camellia.c
     ccm.c
+    chacha20.c
+    chachapoly.c
     cipher.c
     cipher_wrap.c
     cmac.c
@@ -29,6 +31,7 @@
     error.c
     gcm.c
     havege.c
+    hkdf.c
     hmac_drbg.c
     md.c
     md2.c
@@ -46,6 +49,8 @@
     pkparse.c
     pkwrite.c
     platform.c
+    platform_util.c
+    poly1305.c
     ripemd160.c
     rsa.c
     rsa_internal.c
@@ -141,15 +146,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..c8782ca 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
@@ -50,18 +50,21 @@
 OBJS_CRYPTO=	aes.o		aesni.o		arc4.o		\
 		asn1parse.o	asn1write.o	base64.o	\
 		bignum.o	blowfish.o	camellia.o	\
-		ccm.o		cipher.o	cipher_wrap.o	\
+		ccm.o		chacha20.o	chachapoly.o	\
+		cipher.o	cipher_wrap.o			\
 		cmac.o		ctr_drbg.o	des.o		\
 		dhm.o		ecdh.o		ecdsa.o		\
 		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	\
+		platform_util.o	poly1305.o			\
 		ripemd160.o	rsa_internal.o	rsa.o  		\
 		sha1.o		sha256.o	sha512.o	\
 		threading.o	timing.o	version.o	\
diff --git a/library/aes.c b/library/aes.c
index da94b19..59c5165 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,9 +518,23 @@
     if( ctx == NULL )
         return;
 
-    mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
 }
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
+{
+    mbedtls_aes_init( &ctx->crypt );
+    mbedtls_aes_init( &ctx->tweak );
+}
+
+void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx )
+{
+    mbedtls_aes_free( &ctx->crypt );
+    mbedtls_aes_free( &ctx->tweak );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 /*
  * AES key schedule (encryption)
  */
@@ -706,6 +716,45 @@
 
     return( ret );
 }
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int mbedtls_aes_xts_setkey( mbedtls_aes_xts_context *ctx,
+                                   const unsigned char *key,
+                                   unsigned int keybits,
+                                   int (*setkey1)( mbedtls_aes_context *ctx,
+                                                   const unsigned char *key,
+                                                   unsigned int keybits ) )
+{
+    const unsigned int key1bits = keybits / 2;
+    const unsigned int key2bits = keybits / 2;
+    const unsigned int key1bytes = key1bits / 8;
+    const unsigned char *key1 = &key[0];
+    const unsigned char *key2 = &key[key1bytes];
+    int ret;
+
+    ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
+
+    if( ret )
+        return( ret );
+
+    return( setkey1( &ctx->crypt, key1, key1bits ) );
+}
+
+int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits)
+{
+    return mbedtls_aes_xts_setkey( ctx, key, keybits, mbedtls_aes_setkey_enc );
+}
+
+int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits)
+{
+    return mbedtls_aes_xts_setkey( ctx, key, keybits, mbedtls_aes_setkey_dec );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
 
 #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)         \
@@ -1065,7 +1114,41 @@
 
     return( 0 );
 }
-#endif /*MBEDTLS_CIPHER_MODE_CFB */
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB (Output Feedback Mode) buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+                            size_t length,
+                            size_t *iv_off,
+                            unsigned char iv[16],
+                            const unsigned char *input,
+                            unsigned char *output )
+{
+    int ret = 0;
+    size_t n = *iv_off;
+
+    while( length-- )
+    {
+        if( n == 0 )
+        {
+            ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            if( ret != 0 )
+                goto exit;
+        }
+        *output++ =  *input++ ^ iv[n];
+
+        n = ( n + 1 ) & 0x0F;
+    }
+
+    *iv_off = n;
+
+exit:
+    return( ret );
+}
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 /*
@@ -1103,6 +1186,132 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/*
+ * AES-XTS buffer encryption/decryption
+ */
+
+/* Multiplication by x in the Galois field of GF(2^n) (aka 2, or left shift) */
+static void multiply_by_x_gf128( const unsigned char *in, unsigned char *out )
+{
+    size_t i;
+    const unsigned char overflow = in[15] >> 0x07;
+
+    /* XXX speed up multiplication by going 32-bit at a time instead of 8-bit
+     * */
+    /* Don't we already have functions that can multiply n-bit numbers
+     * efficiently? bignum... mpi... Maybe AES NI can do this multiplication
+     * (galois field 128 multiplication by x, or some sort of lfsr))?*/
+    /* Feedback polynomial: x**128 + x**7 + x**3 + x + 1 (0b10000111)*/
+    i = 16;
+    while( --i ) {
+        const unsigned char carry = in[i - 1] >> 0x07;
+        out[i] = (in[i] << 1) | carry;
+    }
+    out[0] = (in[0] << 1) ^ (overflow ? 0x87 : 0x00);
+}
+
+int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
+                           int mode,
+                           size_t length,
+                           const unsigned char data_unit[16],
+                           const unsigned char *input,
+                           unsigned char *output )
+{
+    size_t blocks = length / 16;
+    size_t leftover = length % 16;
+    unsigned char tweak[16];
+    unsigned char tweak_tmp[16];
+    unsigned char tmp[16];
+
+    /* Sectors must be at least 16 bytes. */
+    if( length < 16)
+        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+
+    /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
+    if( (blocks > 0x100000) || (blocks == 0x100000 && leftover > 0))
+        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+
+    /* Compute the tweak. */
+    memcpy( tweak, data_unit, sizeof(tweak) );
+    mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, tweak, tweak );
+
+    while( blocks-- ) {
+        size_t i;
+
+        /* XXX Code review: Sucks to have conditionals inside this loop.
+         * Suggestions as to whether its worth extracting this outside the toop
+         * are welcome. */
+        if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
+        {
+            /* We are on the last block in a decrypt operation that has
+             * leftover bytes, so we need to use the next tweak for this block,
+             * and this tweak for the lefover bytes. Save the current tweak for
+             * the leftovers and then update the current tweak for use on this,
+             * the last full block. */
+            memcpy( tweak_tmp, tweak, sizeof(tweak));
+            multiply_by_x_gf128( tweak, tweak );
+        }
+
+        /* XXX Code review: Don't we have any functions to more efficiently xor
+         * big nums together than byte-by-byte? */
+        for( i = 0; i < 16; i++ )
+            tmp[i] = input[i] ^ tweak[i];
+
+        mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
+
+        for( i = 0; i < 16; i++ )
+            output[i] = tmp[i] ^ tweak[i];
+
+        /* Update the tweak for the next block */
+        multiply_by_x_gf128( tweak, tweak );
+
+        output += 16;
+        input += 16;
+    }
+
+    if( leftover )
+    {
+        /* If we are on the leftover bytes in a decrypt operation, we need to
+         * use the previous tweak for these bytes (as saved in tweak_tmp). */
+        unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? tweak_tmp : tweak;
+
+        /* We are now on the final part of the data unit, which doesn't divide
+         * evenly by 16. It's time for ciphertext stealing. */
+        size_t i;
+        unsigned char *prev_output = output - 16;
+
+        /* Copy ciphertext bytes from previous block to our output for each
+         * byte of cyphertext we won't steal. At the same time, the remainder
+         * of input for this final round (since the loop bounds are the same).
+         * */
+        /* XXX if we use faster xor functions later here, we'll likely have to
+         * break apart the loop. we might not be able to use faster xor, since
+         * the leftovers could be any number of bytes (not multiples of
+         * 16) (our faster xor would need to support aligned and unaligned
+         * sizes) */
+        for( i = 0; i < leftover; i++ )
+        {
+            output[i] = prev_output[i];
+            tmp[i] = input[i] ^ t[i];
+        }
+
+        /* Copy ciphertext bytes from the previous block for input in this round. */
+        for( ; i < 16; i++)
+            tmp[i] = prev_output[i] ^ t[i];
+
+        mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
+
+        /* Write the result back to the previous block, overriding the previous
+         * output we copied. */
+        for( i = 0; i < 16; i++ )
+            prev_output[i] = tmp[i] ^ t[i];
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 #endif /* !MBEDTLS_AES_ALT */
 
 #if defined(MBEDTLS_SELF_TEST)
@@ -1219,6 +1428,72 @@
 };
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_ofb_key[3][32] =
+{
+    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_ofb_iv[16] =
+{
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_ofb_pt[64] =
+{
+    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_ofb_ct[3][64] =
+{
+    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+      0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
+      0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+      0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
+      0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+      0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
+      0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },
+    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+      0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
+      0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+      0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f,
+      0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+      0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e,
+      0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a },
+    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+      0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,
+      0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+      0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed,
+      0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+      0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,
+      0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 /*
  * AES-CTR test vectors from:
@@ -1282,6 +1557,74 @@
     { 16, 32, 36 };
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/*
+ * AES-XTS test vectors from:
+ *
+ * IEEE P1619/D16 Annex B
+ * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
+ * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf)
+ */
+static const unsigned char aes_test_xts_key[][32] =
+{
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+      0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+    { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+      0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+};
+
+static const unsigned char aes_test_xts_pt32[][32] =
+{
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+    { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+      0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+};
+
+static const unsigned char aes_test_xts_ct32[][32] =
+{
+    { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+      0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+      0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+      0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+    { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+      0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+      0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+      0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+    { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+      0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+      0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+      0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
+};
+
+static const unsigned char aes_test_xts_data_unit[][16] =
+{
+   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+   { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+   { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+};
+
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 /*
  * Checkup routine
  */
@@ -1306,6 +1649,9 @@
     unsigned char nonce_counter[16];
     unsigned char stream_block[16];
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    mbedtls_aes_xts_context ctx_xts;
+#endif
     mbedtls_aes_context ctx;
 
     memset( key, 0, 32 );
@@ -1510,6 +1856,69 @@
         mbedtls_printf( "\n" );
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    /*
+     * OFB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        keybits = 128 + u * 64;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-OFB-%3d (%s): ", keybits,
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  aes_test_ofb_iv, 16 );
+        memcpy( key, aes_test_ofb_key[u], keybits / 8 );
+
+        offset = 0;
+        ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+        /*
+         * AES-192 is an optional feature that may be unavailable when
+         * there is an alternative underlying implementation i.e. when
+         * MBEDTLS_AES_ALT is defined.
+         */
+        if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+        {
+            mbedtls_printf( "skipped\n" );
+            continue;
+        }
+        else if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            memcpy( buf, aes_test_ofb_ct[u], 64 );
+            aes_tests = aes_test_ofb_pt;
+        }
+        else
+        {
+            memcpy( buf, aes_test_ofb_pt, 64 );
+            aes_tests = aes_test_ofb_ct[u];
+        }
+
+        ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf );
+        if( ret != 0 )
+            goto exit;
+
+        if( memcmp( buf, aes_tests, 64 ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     /*
      * CTR mode
@@ -1562,6 +1971,72 @@
         mbedtls_printf( "\n" );
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    {
+    static const int num_tests =
+        sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
+
+    /*
+     * XTS mode
+     */
+    mbedtls_aes_xts_init( &ctx_xts );
+
+    for( i = 0; i < num_tests << 1; i++ )
+    {
+        const unsigned char *data_unit;
+        u = i >> 1;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-XTS-128 (%s): ",
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( key, 0, sizeof( key ) );
+        memcpy( key, aes_test_xts_key[u], 32 );
+        data_unit = aes_test_xts_data_unit[u];
+
+        len = sizeof( *aes_test_xts_ct32 );
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 );
+            if( ret )
+                goto exit;
+            memcpy( buf, aes_test_xts_ct32[u], len );
+            aes_tests = aes_test_xts_pt32[u];
+        }
+        else
+        {
+            ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 );
+            if( ret )
+                goto exit;
+            memcpy( buf, aes_test_xts_pt32[u], len );
+            aes_tests = aes_test_xts_ct32[u];
+        }
+
+
+        ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit,
+                                     buf, buf );
+        if( ret != 0 )
+            goto exit;
+
+        if( memcmp( buf, aes_tests, len ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    mbedtls_aes_xts_free( &ctx_xts );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
     ret = 0;
 
 exit:
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 6b944bf..72b82a0 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 ) );
 }
 
 /*
@@ -341,7 +337,7 @@
                          size_t iv_len, const unsigned char *add,
                          size_t add_len, const unsigned char *input,
                          unsigned char *output, unsigned char *tag,
-                         size_t tag_len, mbedtls_ccm_star_get_iv_t get_iv,
+                         size_t tag_len, mbedtls_ccm_star_get_nonce_t get_iv,
                          void *get_iv_ctx )
 {
     unsigned char iv[CCM_MAX_IV_LEN];
@@ -380,7 +376,7 @@
 
     if( diff != 0 )
     {
-        mbedtls_zeroize( output, length );
+        mbedtls_platform_zeroize( output, length );
         return( MBEDTLS_ERR_CCM_AUTH_FAILED );
     }
 
diff --git a/library/chacha20.c b/library/chacha20.c
new file mode 100644
index 0000000..5a753eb
--- /dev/null
+++ b/library/chacha20.c
@@ -0,0 +1,570 @@
+/**
+ * \file chacha20.c
+ *
+ * \brief ChaCha20 cipher.
+ *
+ * \author Daniel King <damaki.gh@gmail.com>
+ *
+ *  Copyright (C) 2006-2016, 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)
+ */
+#include "mbedtls/chacha20.h"
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CHACHA20_C)
+
+#if !defined(MBEDTLS_CHACHA20_ALT)
+
+#include <stddef.h>
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#define BYTES_TO_U32_LE( data, offset )                           \
+    ( (uint32_t) data[offset]                                     \
+          | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 )   \
+          | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 )  \
+          | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 )  \
+    )
+
+#define ROTL32( value, amount ) ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
+
+#define CHACHA20_CTR_INDEX ( 12U )
+
+#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
+
+/* 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;
+}
+
+/**
+ * \brief           ChaCha20 quarter round operation.
+ *
+ *                  The quarter round is defined as follows (from RFC 7539):
+ *                      1.  a += b; d ^= a; d <<<= 16;
+ *                      2.  c += d; b ^= c; b <<<= 12;
+ *                      3.  a += b; d ^= a; d <<<= 8;
+ *                      4.  c += d; b ^= c; b <<<= 7;
+ *
+ * \param state     ChaCha20 state to modify.
+ * \param a         The index of 'a' in the state.
+ * \param b         The index of 'b' in the state.
+ * \param c         The index of 'c' in the state.
+ * \param d         The index of 'd' in the state.
+ */
+static inline void mbedtls_chacha20_quarter_round( uint32_t state[16],
+                                                   size_t a,
+                                                   size_t b,
+                                                   size_t c,
+                                                   size_t d )
+{
+    /* a += b; d ^= a; d <<<= 16; */
+    state[a] += state[b];
+    state[d] ^= state[a];
+    state[d] = ROTL32( state[d], 16 );
+
+    /* c += d; b ^= c; b <<<= 12 */
+    state[c] += state[d];
+    state[b] ^= state[c];
+    state[b] = ROTL32( state[b], 12 );
+
+    /* a += b; d ^= a; d <<<= 8; */
+    state[a] += state[b];
+    state[d] ^= state[a];
+    state[d] = ROTL32( state[d], 8 );
+
+    /* c += d; b ^= c; b <<<= 7; */
+    state[c] += state[d];
+    state[b] ^= state[c];
+    state[b] = ROTL32( state[b], 7 );
+}
+
+/**
+ * \brief           Perform the ChaCha20 inner block operation.
+ *
+ *                  This function performs two rounds: the column round and the
+ *                  diagonal round.
+ *
+ * \param state     The ChaCha20 state to update.
+ */
+static void mbedtls_chacha20_inner_block( uint32_t state[16] )
+{
+    mbedtls_chacha20_quarter_round( state, 0, 4, 8,  12 );
+    mbedtls_chacha20_quarter_round( state, 1, 5, 9,  13 );
+    mbedtls_chacha20_quarter_round( state, 2, 6, 10, 14 );
+    mbedtls_chacha20_quarter_round( state, 3, 7, 11, 15 );
+
+    mbedtls_chacha20_quarter_round( state, 0, 5, 10, 15 );
+    mbedtls_chacha20_quarter_round( state, 1, 6, 11, 12 );
+    mbedtls_chacha20_quarter_round( state, 2, 7, 8,  13 );
+    mbedtls_chacha20_quarter_round( state, 3, 4, 9,  14 );
+}
+
+/**
+ * \brief               Generates a keystream block.
+ *
+ * \param initial_state The initial ChaCha20 state (containing the key, nonce, counter).
+ * \param working_state This state is used as a temporary working area.
+ * \param keystream     Generated keystream bytes are written to this buffer.
+ */
+static void mbedtls_chacha20_block( const uint32_t initial_state[16],
+                                    uint32_t working_state[16],
+                                    unsigned char keystream[64] )
+{
+    size_t i;
+    size_t offset;
+
+    memcpy( working_state,
+            initial_state,
+            CHACHA20_BLOCK_SIZE_BYTES );
+
+    for ( i = 0U; i < 10U; i++ )
+    {
+        mbedtls_chacha20_inner_block( working_state );
+    }
+
+    working_state[0]  += initial_state[0];
+    working_state[1]  += initial_state[1];
+    working_state[2]  += initial_state[2];
+    working_state[3]  += initial_state[3];
+    working_state[4]  += initial_state[4];
+    working_state[5]  += initial_state[5];
+    working_state[6]  += initial_state[6];
+    working_state[7]  += initial_state[7];
+    working_state[8]  += initial_state[8];
+    working_state[9]  += initial_state[9];
+    working_state[10] += initial_state[10];
+    working_state[11] += initial_state[11];
+    working_state[12] += initial_state[12];
+    working_state[13] += initial_state[13];
+    working_state[14] += initial_state[14];
+    working_state[15] += initial_state[15];
+
+    for ( i = 0U; i < 16; i++ )
+    {
+        offset = i * 4U;
+
+        keystream[offset     ] = (unsigned char)   working_state[i];
+        keystream[offset + 1U] = (unsigned char) ( working_state[i] >> 8  );
+        keystream[offset + 2U] = (unsigned char) ( working_state[i] >> 16 );
+        keystream[offset + 3U] = (unsigned char) ( working_state[i] >> 24 );
+    }
+}
+
+void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
+{
+    if ( ctx != NULL )
+    {
+        mbedtls_zeroize( ctx->initial_state, sizeof( ctx->initial_state ) );
+        mbedtls_zeroize( ctx->working_state, sizeof( ctx->working_state ) );
+        mbedtls_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
+
+        /* Initially, there's no keystream bytes available */
+        ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
+    }
+}
+
+void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
+{
+    if ( ctx != NULL )
+    {
+        mbedtls_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
+    }
+}
+
+int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
+                            const unsigned char key[32] )
+{
+    if ( ( ctx == NULL ) || ( key == NULL ) )
+    {
+        return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    }
+
+    /* ChaCha20 constants - the string "expand 32-byte k" */
+    ctx->initial_state[0] = 0x61707865;
+    ctx->initial_state[1] = 0x3320646e;
+    ctx->initial_state[2] = 0x79622d32;
+    ctx->initial_state[3] = 0x6b206574;
+
+    /* Set key */
+    ctx->initial_state[4]  = BYTES_TO_U32_LE( key, 0 );
+    ctx->initial_state[5]  = BYTES_TO_U32_LE( key, 4 );
+    ctx->initial_state[6]  = BYTES_TO_U32_LE( key, 8 );
+    ctx->initial_state[7]  = BYTES_TO_U32_LE( key, 12 );
+    ctx->initial_state[8]  = BYTES_TO_U32_LE( key, 16 );
+    ctx->initial_state[9]  = BYTES_TO_U32_LE( key, 20 );
+    ctx->initial_state[10] = BYTES_TO_U32_LE( key, 24 );
+    ctx->initial_state[11] = BYTES_TO_U32_LE( key, 28 );
+
+    return( 0 );
+}
+
+int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
+                             const unsigned char nonce[12],
+                             uint32_t counter )
+{
+    if ( ( ctx == NULL ) || ( nonce == NULL ) )
+    {
+        return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    }
+
+    /* Counter */
+    ctx->initial_state[12] = counter;
+
+    /* Nonce */
+    ctx->initial_state[13] = BYTES_TO_U32_LE( nonce, 0 );
+    ctx->initial_state[14] = BYTES_TO_U32_LE( nonce, 4 );
+    ctx->initial_state[15] = BYTES_TO_U32_LE( nonce, 8 );
+
+    mbedtls_zeroize( ctx->working_state, sizeof( ctx->working_state ) );
+    mbedtls_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
+
+    /* Initially, there's no keystream bytes available */
+    ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
+
+    return( 0 );
+}
+
+int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
+                              size_t size,
+                              const unsigned char *input,
+                              unsigned char *output )
+{
+    size_t offset = 0U;
+    size_t i;
+
+    if ( ctx == NULL )
+    {
+        return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    }
+    else if ( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
+    {
+        /* input and output pointers are allowed to be NULL only if size == 0 */
+        return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    }
+
+    /* Use leftover keystream bytes, if available */
+    while ( ( size > 0U ) && ( ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) )
+    {
+        output[offset] = input[offset] ^ ctx->keystream8[ctx->keystream_bytes_used];
+
+        ctx->keystream_bytes_used++;
+        offset++;
+        size--;
+    }
+
+    /* Process full blocks */
+    while ( size >= CHACHA20_BLOCK_SIZE_BYTES )
+    {
+        /* Generate new keystream block and increment counter */
+        mbedtls_chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
+        ctx->initial_state[CHACHA20_CTR_INDEX]++;
+
+        for ( i = 0U; i < 64U; i += 8U )
+        {
+            output[offset + i      ] = input[offset + i      ] ^ ctx->keystream8[i      ];
+            output[offset + i + 1U ] = input[offset + i + 1U ] ^ ctx->keystream8[i + 1U ];
+            output[offset + i + 2U ] = input[offset + i + 2U ] ^ ctx->keystream8[i + 2U ];
+            output[offset + i + 3U ] = input[offset + i + 3U ] ^ ctx->keystream8[i + 3U ];
+            output[offset + i + 4U ] = input[offset + i + 4U ] ^ ctx->keystream8[i + 4U ];
+            output[offset + i + 5U ] = input[offset + i + 5U ] ^ ctx->keystream8[i + 5U ];
+            output[offset + i + 6U ] = input[offset + i + 6U ] ^ ctx->keystream8[i + 6U ];
+            output[offset + i + 7U ] = input[offset + i + 7U ] ^ ctx->keystream8[i + 7U ];
+        }
+
+        offset += CHACHA20_BLOCK_SIZE_BYTES;
+        size   -= CHACHA20_BLOCK_SIZE_BYTES;
+    }
+
+    /* Last (partial) block */
+    if ( size > 0U )
+    {
+        /* Generate new keystream block and increment counter */
+        mbedtls_chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
+        ctx->initial_state[CHACHA20_CTR_INDEX]++;
+
+        for ( i = 0U; i < size; i++)
+        {
+            output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
+        }
+
+        ctx->keystream_bytes_used = size;
+
+    }
+
+    return( 0 );
+}
+
+int mbedtls_chacha20_crypt( const unsigned char key[32],
+                            const unsigned char nonce[12],
+                            uint32_t counter,
+                            size_t data_len,
+                            const unsigned char* input,
+                            unsigned char* output )
+{
+    mbedtls_chacha20_context ctx;
+    int result;
+
+    mbedtls_chacha20_init( &ctx );
+
+    result = mbedtls_chacha20_setkey( &ctx, key );
+    if ( result != 0 )
+        goto cleanup;
+
+    result = mbedtls_chacha20_starts( &ctx, nonce, counter );
+    if ( result != 0 )
+        goto cleanup;
+
+    result = mbedtls_chacha20_update( &ctx, data_len, input, output );
+
+cleanup:
+    mbedtls_chacha20_free( &ctx );
+    return( result );
+}
+
+#endif /* !MBEDTLS_CHACHA20_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char test_keys[2][32] =
+{
+    {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    },
+    {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+    }
+};
+
+static const unsigned char test_nonces[2][12] =
+{
+    {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00
+    },
+    {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x02
+    }
+};
+
+static const uint32_t test_counters[2] =
+{
+    0U,
+    1U
+};
+
+static const unsigned char test_input[2][375] =
+{
+    {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    },
+    {
+        0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
+        0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
+        0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
+        0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
+        0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
+        0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
+        0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
+        0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
+        0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
+        0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
+        0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
+        0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
+        0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+        0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
+        0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
+        0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
+        0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+        0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
+        0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+        0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
+        0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
+        0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
+        0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
+        0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
+        0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
+        0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
+        0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+        0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
+        0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
+        0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
+        0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
+        0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
+        0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
+        0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
+        0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
+        0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+        0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
+        0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
+        0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
+        0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
+        0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
+        0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
+        0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
+        0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
+        0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
+        0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
+        0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
+    }
+};
+
+static const unsigned char test_output[2][375] =
+{
+    {
+        0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+        0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+        0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+        0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
+        0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
+        0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
+        0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
+        0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
+    },
+    {
+        0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
+        0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
+        0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
+        0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
+        0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
+        0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
+        0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
+        0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
+        0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
+        0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
+        0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
+        0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
+        0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
+        0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
+        0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
+        0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
+        0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
+        0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
+        0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
+        0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
+        0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
+        0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
+        0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
+        0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
+        0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
+        0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
+        0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
+        0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
+        0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
+        0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
+        0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
+        0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
+        0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
+        0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
+        0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
+        0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
+        0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
+        0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
+        0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
+        0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
+        0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
+        0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
+        0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
+        0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
+        0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
+        0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
+        0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
+    }
+};
+
+static const size_t test_lengths[2] =
+{
+    64U,
+    375U
+};
+
+#define ASSERT( cond, args )            \
+    do                                  \
+    {                                   \
+        if( ! ( cond ) )                \
+        {                               \
+            if( verbose != 0 )          \
+                mbedtls_printf args;    \
+                                        \
+            return( -1 );               \
+        }                               \
+    }                                   \
+    while( 0 )
+
+int mbedtls_chacha20_self_test( int verbose )
+{
+    unsigned char output[381];
+    unsigned i;
+    int result;
+
+    for( i = 0U; i < 2U; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  ChaCha20 test %u ", i );
+
+        result = mbedtls_chacha20_crypt( test_keys[i],
+                                         test_nonces[i],
+                                         test_counters[i],
+                                         test_lengths[i],
+                                         test_input[i],
+                                         output );
+
+        ASSERT( 0 == result, ( "error code: %i\n", result ) );
+
+        ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
+                ( "failed (output)\n" ) );
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* !MBEDTLS_CHACHA20_C */
diff --git a/library/chachapoly.c b/library/chachapoly.c
new file mode 100644
index 0000000..ebf25bb
--- /dev/null
+++ b/library/chachapoly.c
@@ -0,0 +1,518 @@
+/**
+ * \file chachapoly.c
+ *
+ * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
+ *
+ *  Copyright (C) 2006-2016, 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_CHACHAPOLY_C)
+
+#include "mbedtls/chachapoly.h"
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#if !defined(MBEDTLS_CHACHAPOLY_ALT)
+
+#define CHACHAPOLY_STATE_INIT       ( 0 )
+#define CHACHAPOLY_STATE_AAD        ( 1 )
+#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
+#define CHACHAPOLY_STATE_FINISHED   ( 3 )
+
+/* 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;
+}
+
+/**
+ * \brief           Adds padding bytes (zeroes) to pad the AAD for Poly1305.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context.
+ */
+static void mbedtls_chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
+{
+    uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
+    unsigned char zeroes[15];
+
+    if ( partial_block_len > 0U )
+    {
+        memset( zeroes, 0, sizeof( zeroes ) );
+        (void) mbedtls_poly1305_update( &ctx->poly1305_ctx,
+                                        zeroes,
+                                        16U - partial_block_len );
+    }
+}
+
+/**
+ * \brief           Adds padding bytes (zeroes) to pad the ciphertext for Poly1305.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context.
+ */
+static void mbedtls_chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
+{
+    uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
+    unsigned char zeroes[15];
+
+    if ( partial_block_len > 0U )
+    {
+        memset( zeroes, 0, sizeof( zeroes ) );
+        (void) mbedtls_poly1305_update( &ctx->poly1305_ctx,
+                                        zeroes,
+                                        16U - partial_block_len );
+    }
+}
+
+void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
+{
+    if ( ctx != NULL )
+    {
+        mbedtls_chacha20_init( &ctx->chacha20_ctx );
+        mbedtls_poly1305_init( &ctx->poly1305_ctx );
+        ctx->aad_len        = 0U;
+        ctx->ciphertext_len = 0U;
+        ctx->state          = CHACHAPOLY_STATE_INIT;
+        ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
+    }
+}
+
+void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
+{
+    if ( ctx != NULL )
+    {
+        mbedtls_chacha20_free( &ctx->chacha20_ctx );
+        mbedtls_poly1305_free( &ctx->poly1305_ctx );
+        ctx->aad_len        = 0U;
+        ctx->ciphertext_len = 0U;
+        ctx->state          = CHACHAPOLY_STATE_INIT;
+        ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
+    }
+}
+
+int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
+                               const unsigned char key[32] )
+{
+    int result;
+
+    if ( ( ctx == NULL ) || ( key == NULL ) )
+    {
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    }
+
+    result = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
+
+    return( result );
+}
+
+int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
+                               const unsigned char nonce[12],
+                               mbedtls_chachapoly_mode_t mode  )
+{
+    int result;
+    unsigned char poly1305_key[64];
+
+    if ( ( ctx == NULL ) || ( nonce == NULL ) )
+    {
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    }
+
+    /* Set counter = 0, will be update to 1 when generating Poly1305 key */
+    result = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
+    if ( result != 0 )
+        goto cleanup;
+
+    /* Generate the Poly1305 key by getting the ChaCha20 keystream output with counter = 0.
+     * This is the same as encrypting a buffer of zeroes.
+     * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
+     * The other 256 bits are discarded.
+     */
+    memset( poly1305_key, 0, sizeof( poly1305_key ) );
+    result = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
+                                      poly1305_key, poly1305_key );
+    if ( result != 0 )
+        goto cleanup;
+
+    result = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
+
+    if ( result == 0 )
+    {
+        ctx->aad_len        = 0U;
+        ctx->ciphertext_len = 0U;
+        ctx->state          = CHACHAPOLY_STATE_AAD;
+        ctx->mode           = mode;
+    }
+
+cleanup:
+    mbedtls_zeroize( poly1305_key, 64U );
+    return( result );
+}
+
+int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
+                                   const unsigned char *aad,
+                                   size_t aad_len )
+{
+    if ( ctx == NULL )
+    {
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    }
+    else if ( ( aad_len > 0U ) && ( aad == NULL ) )
+    {
+        /* aad pointer is allowed to be NULL if aad_len == 0 */
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    }
+    else if ( ctx->state != CHACHAPOLY_STATE_AAD )
+    {
+        return(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    }
+
+    ctx->aad_len += aad_len;
+
+    return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
+}
+
+int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
+                               size_t len,
+                               const unsigned char *input,
+                               unsigned char *output )
+{
+    if ( ctx == NULL )
+    {
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    }
+    else if ( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
+    {
+        /* input and output pointers are allowed to be NULL if len == 0 */
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    }
+    else if ( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
+              ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
+    {
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    }
+
+    if ( ctx->state == CHACHAPOLY_STATE_AAD )
+    {
+        ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
+
+        mbedtls_chachapoly_pad_aad( ctx );
+    }
+
+    ctx->ciphertext_len += len;
+
+    if ( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
+    {
+        /* Note: the following functions return an error only if one or more of
+         *       the input pointers are NULL. Since we have checked their validity
+         *       above, we can safety ignore the return value.
+         */
+        (void) mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
+        (void) mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
+    }
+    else /* DECRYPT */
+    {
+        (void) mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
+        (void) mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
+    }
+
+    return( 0 );
+}
+
+int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
+                               unsigned char mac[16] )
+{
+    unsigned char len_block[16];
+
+    if ( ( ctx == NULL ) || ( mac == NULL ) )
+    {
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    }
+    else if ( ctx->state == CHACHAPOLY_STATE_INIT )
+    {
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    }
+
+    if ( ctx->state == CHACHAPOLY_STATE_AAD )
+    {
+        mbedtls_chachapoly_pad_aad( ctx );
+    }
+    else if ( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
+    {
+        mbedtls_chachapoly_pad_ciphertext( ctx );
+    }
+
+    ctx->state = CHACHAPOLY_STATE_FINISHED;
+
+    /* The lengths of the AAD and ciphertext are processed by
+     * Poly1305 as the final 128-bit block, encoded as little-endian integers.
+     */
+    len_block[0]  = (unsigned char) ctx->aad_len;
+    len_block[1]  = (unsigned char) ( ctx->aad_len >> 8 );
+    len_block[2]  = (unsigned char) ( ctx->aad_len >> 16 );
+    len_block[3]  = (unsigned char) ( ctx->aad_len >> 24 );
+    len_block[4]  = (unsigned char) ( ctx->aad_len >> 32 );
+    len_block[5]  = (unsigned char) ( ctx->aad_len >> 40 );
+    len_block[6]  = (unsigned char) ( ctx->aad_len >> 48 );
+    len_block[7]  = (unsigned char) ( ctx->aad_len >> 56 );
+    len_block[8]  = (unsigned char) ctx->ciphertext_len;
+    len_block[9]  = (unsigned char) ( ctx->ciphertext_len >> 8 );
+    len_block[10] = (unsigned char) ( ctx->ciphertext_len >> 16 );
+    len_block[11] = (unsigned char) ( ctx->ciphertext_len >> 24 );
+    len_block[12] = (unsigned char) ( ctx->ciphertext_len >> 32 );
+    len_block[13] = (unsigned char) ( ctx->ciphertext_len >> 40 );
+    len_block[14] = (unsigned char) ( ctx->ciphertext_len >> 48 );
+    len_block[15] = (unsigned char) ( ctx->ciphertext_len >> 56 );
+
+    (void) mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
+    (void) mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
+
+    return( 0 );
+}
+
+int mbedtls_chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
+                                      mbedtls_chachapoly_mode_t mode,
+                                      size_t length,
+                                      const unsigned char nonce[12],
+                                      const unsigned char *aad,
+                                      size_t aad_len,
+                                      const unsigned char *input,
+                                      unsigned char *output,
+                                      unsigned char tag[16] )
+{
+    int result;
+
+    result = mbedtls_chachapoly_starts( ctx, nonce, mode );
+    if ( result != 0 )
+        goto cleanup;
+
+    result = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
+    if ( result != 0 )
+            goto cleanup;
+
+    result = mbedtls_chachapoly_update( ctx, length, input, output );
+    if ( result != 0 )
+            goto cleanup;
+
+    result = mbedtls_chachapoly_finish( ctx, tag );
+
+cleanup:
+    return( result );
+}
+
+int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
+                                     size_t length,
+                                     const unsigned char nonce[12],
+                                     const unsigned char *aad,
+                                     size_t aad_len,
+                                     const unsigned char tag[16],
+                                     const unsigned char *input,
+                                     unsigned char *output )
+{
+    int ret;
+    unsigned char check_tag[16];
+    size_t i;
+    int diff;
+
+    if( tag == NULL )
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+
+    if( ( ret = mbedtls_chachapoly_crypt_and_tag( ctx,
+                        MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
+                        aad, aad_len, input, output, check_tag ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /* Check tag in "constant-time" */
+    for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
+        diff |= tag[i] ^ check_tag[i];
+
+    if( diff != 0 )
+    {
+        mbedtls_zeroize( output, length );
+        return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
+    }
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_CHACHAPOLY_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char test_key[1][32] =
+{
+    {
+        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+        0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+        0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
+    }
+};
+
+static const unsigned char test_nonce[1][12] =
+{
+    {
+        0x07, 0x00, 0x00, 0x00,                         /* 32-bit common part */
+        0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47  /* 64-bit IV */
+    }
+};
+
+static const unsigned char test_aad[1][12] =
+{
+    {
+        0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
+        0xc4, 0xc5, 0xc6, 0xc7
+    }
+};
+
+static const size_t test_aad_len[1] =
+{
+    12U
+};
+
+static const unsigned char test_input[1][114] =
+{
+    {
+        0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
+        0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
+        0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+        0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
+        0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
+        0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
+        0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
+        0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
+        0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
+        0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
+        0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
+        0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
+        0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
+        0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
+        0x74, 0x2e
+    }
+};
+
+static const unsigned char test_output[1][114] =
+{
+    {
+        0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
+        0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
+        0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
+        0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
+        0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
+        0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
+        0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
+        0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
+        0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
+        0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
+        0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
+        0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
+        0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
+        0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
+        0x61, 0x16
+    }
+};
+
+static const size_t test_input_len[1] =
+{
+    114U
+};
+
+static const unsigned char test_mac[1][16] =
+{
+    {
+        0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
+        0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
+    }
+};
+
+#define ASSERT( cond, args )            \
+    do                                  \
+    {                                   \
+        if( ! ( cond ) )                \
+        {                               \
+            if( verbose != 0 )          \
+                mbedtls_printf args;    \
+                                        \
+            return( -1 );               \
+        }                               \
+    }                                   \
+    while( 0 )
+
+int mbedtls_chachapoly_self_test( int verbose )
+{
+    mbedtls_chachapoly_context ctx;
+    unsigned i;
+    int result;
+    unsigned char output[200];
+    unsigned char mac[16];
+
+    for( i = 0U; i < 1U; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  ChaCha20-Poly1305 test %u ", i );
+
+        mbedtls_chachapoly_init( &ctx );
+
+        result = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
+        ASSERT( 0 == result, ( "setkey() error code: %i\n", result ) );
+
+        result = mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                                   MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                                   test_input_len[i],
+                                                   test_nonce[i],
+                                                   test_aad[i],
+                                                   test_aad_len[i],
+                                                   test_input[i],
+                                                   output,
+                                                   mac );
+
+        ASSERT( 0 == result, ( "crypt_and_tag() error code: %i\n", result ) );
+
+        ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
+                ( "failure (wrong output)\n" ) );
+
+        ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
+                ( "failure (wrong MAC)\n" ) );
+
+        mbedtls_chachapoly_free( &ctx );
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_CHACHAPOLY_C */
diff --git a/library/cipher.c b/library/cipher.c
index 7369f48..b204bcb 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -33,10 +33,15 @@
 
 #include "mbedtls/cipher.h"
 #include "mbedtls/cipher_internal.h"
+#include "mbedtls/platform_util.h"
 
 #include <stdlib.h>
 #include <string.h>
 
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#include "mbedtls/chachapoly.h"
+#endif
+
 #if defined(MBEDTLS_GCM_C)
 #include "mbedtls/gcm.h"
 #endif
@@ -45,6 +50,10 @@
 #include "mbedtls/ccm.h"
 #endif
 
+#if defined(MBEDTLS_CHACHA20_C)
+#include "mbedtls/chacha20.h"
+#endif
+
 #if defined(MBEDTLS_CMAC_C)
 #include "mbedtls/cmac.h"
 #endif
@@ -60,10 +69,26 @@
 #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;
+
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
+/* Compare the contents of two buffers in constant time.
+ * Returns 0 if the contents are bitwise identical, otherwise returns
+ * a non-zero value.
+ * This is currently only used by GCM and ChaCha20+Poly1305.
+ */
+static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len )
+{
+    const unsigned char *p1 = (const unsigned char*) v1;
+    const unsigned char *p2 = (const unsigned char*) v2;
+    size_t i;
+    unsigned char diff;
+
+    for( diff = 0, i = 0; i < len; i++ )
+        diff |= p1[i] ^ p2[i];
+
+    return (int)diff;
 }
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
 
 static int supported_init = 0;
 
@@ -141,7 +166,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 +175,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 )
@@ -194,10 +220,11 @@
     ctx->operation = operation;
 
     /*
-     * For CFB and CTR mode always use the encryption key schedule
+     * For OFB, CFB and CTR mode always use the encryption key schedule
      */
     if( MBEDTLS_ENCRYPT == operation ||
         MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
         MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
     {
         return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
@@ -234,6 +261,18 @@
             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
     }
 
+#if defined(MBEDTLS_CHACHA20_C)
+    if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
+    {
+        if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
+                                           iv,
+                                           0U ) ) /* Initial counter value */
+        {
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+    }
+#endif
+
     memcpy( ctx->iv, iv, actual_iv_size );
     ctx->iv_size = actual_iv_size;
 
@@ -250,22 +289,45 @@
     return( 0 );
 }
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
 int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
                       const unsigned char *ad, size_t ad_len )
 {
     if( NULL == ctx || NULL == ctx->cipher_info )
         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
+#if defined(MBEDTLS_GCM_C)
     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
     {
         return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
                            ctx->iv, ctx->iv_size, ad, ad_len );
     }
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+    {
+        int result;
+        mbedtls_chachapoly_mode_t mode;
+
+        mode = ( ctx->operation == MBEDTLS_ENCRYPT )
+                ? MBEDTLS_CHACHAPOLY_ENCRYPT
+                : MBEDTLS_CHACHAPOLY_DECRYPT;
+
+        result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+                                                        ctx->iv,
+                                                        mode );
+        if ( result != 0 )
+            return( result );
+
+        return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+                                                          ad, ad_len );
+    }
+#endif
 
     return( 0 );
 }
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
 
 int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
                    size_t ilen, unsigned char *output, size_t *olen )
@@ -306,6 +368,15 @@
     }
 #endif
 
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
+    {
+        *olen = ilen;
+        return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+                                                      ilen, input, output );
+    }
+#endif
+
     if ( 0 == block_size )
     {
         return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
@@ -427,6 +498,21 @@
     }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
+    {
+        if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
+                ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
+        {
+            return( ret );
+        }
+
+        *olen = ilen;
+
+        return( 0 );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
     {
@@ -443,6 +529,27 @@
     }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
+    {
+        if ( ctx->unprocessed_len ) {
+            /* We can only process an entire sector at a time. */
+            return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        }
+
+        ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
+                ctx->operation, ilen, ctx->iv, input, output );
+        if( ret != 0 )
+        {
+            return( ret );
+        }
+
+        *olen = ilen;
+
+        return( 0 );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
     {
@@ -642,13 +749,21 @@
     *olen = 0;
 
     if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
         MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
         MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
         MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
     {
         return( 0 );
     }
 
+    if ( ( MBEDTLS_CIPHER_CHACHA20          == ctx->cipher_info->type ) ||
+         ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
+    {
+        return( 0 );
+    }
+
     if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
     {
         if( ctx->unprocessed_len != 0 )
@@ -760,7 +875,7 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
 int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
                       unsigned char *tag, size_t tag_len )
 {
@@ -770,8 +885,22 @@
     if( MBEDTLS_ENCRYPT != ctx->operation )
         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
+#if defined(MBEDTLS_GCM_C)
     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
         return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+    {
+        /* Don't allow truncated MAC for Poly1305 */
+        if ( tag_len != 16U )
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+        return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+                                                      tag );
+    }
+#endif
 
     return( 0 );
 }
@@ -779,6 +908,7 @@
 int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
                       const unsigned char *tag, size_t tag_len )
 {
+    unsigned char check_tag[16];
     int ret;
 
     if( NULL == ctx || NULL == ctx->cipher_info ||
@@ -787,12 +917,9 @@
         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
     }
 
+#if defined(MBEDTLS_GCM_C)
     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
     {
-        unsigned char check_tag[16];
-        size_t i;
-        int diff;
-
         if( tag_len > sizeof( check_tag ) )
             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
@@ -803,18 +930,38 @@
         }
 
         /* Check the tag in "constant-time" */
-        for( diff = 0, i = 0; i < tag_len; i++ )
-            diff |= tag[i] ^ check_tag[i];
-
-        if( diff != 0 )
+        if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
             return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
 
         return( 0 );
     }
+#endif /* MBEDTLS_GCM_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+    {
+        /* Don't allow truncated MAC for Poly1305 */
+        if ( tag_len != sizeof( check_tag ) )
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+        ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
+                                                     check_tag );
+        if ( ret != 0 )
+        {
+            return( ret );
+        }
+
+        /* Check the tag in "constant-time" */
+        if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
+            return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
+
+        return( 0 );
+    }
+#endif /* MBEDTLS_CHACHAPOLY_C */
 
     return( 0 );
 }
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
 
 /*
  * Packet-oriented wrapper for non-AEAD modes
@@ -873,6 +1020,22 @@
                                      tag, tag_len ) );
     }
 #endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+    {
+        /* ChachaPoly has fixed length nonce and MAC (tag) */
+        if ( ( iv_len != ctx->cipher_info->iv_size ) ||
+             ( tag_len != 16U ) )
+        {
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+
+        *olen = ilen;
+        return( mbedtls_chachapoly_crypt_and_tag( ctx->cipher_ctx,
+                                MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                ilen, iv, ad, ad_len, input, output, tag ) );
+    }
+#endif /* MBEDTLS_CHACHAPOLY_C */
 
     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
 }
@@ -919,6 +1082,28 @@
         return( ret );
     }
 #endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+    {
+        int ret;
+
+        /* ChachaPoly has fixed length nonce and MAC (tag) */
+        if ( ( iv_len != ctx->cipher_info->iv_size ) ||
+             ( tag_len != 16U ) )
+        {
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+
+        *olen = ilen;
+        ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen,
+                                iv, ad, ad_len, tag, input, output );
+
+        if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED )
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+
+        return( ret );
+    }
+#endif /* MBEDTLS_CHACHAPOLY_C */
 
     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
 }
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index dc76af8..0ab4971 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -33,6 +33,10 @@
 
 #include "mbedtls/cipher_internal.h"
 
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#include "mbedtls/chachapoly.h"
+#endif
+
 #if defined(MBEDTLS_AES_C)
 #include "mbedtls/aes.h"
 #endif
@@ -53,6 +57,10 @@
 #include "mbedtls/blowfish.h"
 #endif
 
+#if defined(MBEDTLS_CHACHA20_C)
+#include "mbedtls/chacha20.h"
+#endif
+
 #if defined(MBEDTLS_GCM_C)
 #include "mbedtls/gcm.h"
 #endif
@@ -138,6 +146,15 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off,
+                                    iv, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
         unsigned char *nonce_counter, unsigned char *stream_block,
@@ -148,6 +165,33 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation,
+                               size_t length,
+                               const unsigned char data_unit[16],
+                               const unsigned char *input,
+                               unsigned char *output )
+{
+    mbedtls_aes_xts_context *xts_ctx = ctx;
+    int mode;
+
+    switch (operation)
+    {
+        case MBEDTLS_ENCRYPT:
+            mode = MBEDTLS_AES_ENCRYPT;
+            break;
+        case MBEDTLS_DECRYPT:
+            mode = MBEDTLS_AES_DECRYPT;
+            break;
+        default:
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+    return mbedtls_aes_crypt_xts( xts_ctx, mode, length,
+                                  data_unit, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
                                 unsigned int key_bitlen )
 {
@@ -187,9 +231,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     aes_crypt_cfb128_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    aes_crypt_ofb_wrap,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     aes_crypt_ctr_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -302,6 +352,41 @@
 };
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+static const mbedtls_cipher_info_t aes_128_ofb_info = {
+    MBEDTLS_CIPHER_AES_128_OFB,
+    MBEDTLS_MODE_OFB,
+    128,
+    "AES-128-OFB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_ofb_info = {
+    MBEDTLS_CIPHER_AES_192_OFB,
+    MBEDTLS_MODE_OFB,
+    192,
+    "AES-192-OFB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_ofb_info = {
+    MBEDTLS_CIPHER_AES_256_OFB,
+    MBEDTLS_MODE_OFB,
+    256,
+    "AES-256-OFB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 static const mbedtls_cipher_info_t aes_128_ctr_info = {
     MBEDTLS_CIPHER_AES_128_CTR,
@@ -337,6 +422,92 @@
 };
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
+                                    unsigned int key_bitlen )
+{
+    mbedtls_aes_xts_context *xts_ctx = ctx;
+    return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) );
+}
+
+static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
+                                    unsigned int key_bitlen )
+{
+    mbedtls_aes_xts_context *xts_ctx = ctx;
+    return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) );
+}
+
+static void *xts_aes_ctx_alloc( void )
+{
+    mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) );
+
+    if( xts_ctx )
+        mbedtls_aes_xts_init( xts_ctx );
+
+    return( xts_ctx );
+}
+
+static void xts_aes_ctx_free( void *ctx )
+{
+    mbedtls_aes_xts_context *xts_ctx = ctx;
+
+    if ( !xts_ctx )
+        return;
+
+    mbedtls_aes_xts_free( xts_ctx );
+    mbedtls_free( xts_ctx );
+}
+
+static const mbedtls_cipher_base_t xts_aes_info = {
+    MBEDTLS_CIPHER_ID_AES,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    aes_crypt_xts_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    xts_aes_setkey_enc_wrap,
+    xts_aes_setkey_dec_wrap,
+    xts_aes_ctx_alloc,
+    xts_aes_ctx_free
+};
+
+static const mbedtls_cipher_info_t aes_128_xts_info = {
+    MBEDTLS_CIPHER_AES_128_XTS,
+    MBEDTLS_MODE_XTS,
+    256,
+    "AES-128-XTS",
+    16,
+    0,
+    16,
+    &xts_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_xts_info = {
+    MBEDTLS_CIPHER_AES_256_XTS,
+    MBEDTLS_MODE_XTS,
+    512,
+    "AES-256-XTS",
+    16,
+    0,
+    16,
+    &xts_aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 #if defined(MBEDTLS_GCM_C)
 static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
                                 unsigned int key_bitlen )
@@ -354,9 +525,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -417,9 +594,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -544,9 +727,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     camellia_crypt_cfb128_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     camellia_crypt_ctr_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -711,9 +900,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -774,9 +969,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -950,9 +1151,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -995,9 +1202,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1040,9 +1253,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1149,9 +1368,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     blowfish_crypt_cfb64_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     blowfish_crypt_ctr_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1259,9 +1484,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     arc4_crypt_stream_wrap,
 #endif
@@ -1283,6 +1514,162 @@
 };
 #endif /* MBEDTLS_ARC4_C */
 
+#if defined(MBEDTLS_CHACHA20_C)
+
+static int chacha20_setkey_wrap( void *ctx, const unsigned char *key,
+                                 unsigned int key_bitlen )
+{
+    if( key_bitlen != 256U )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    return( 0 );
+}
+
+static int chacha20_stream_wrap( void *ctx,  size_t length,
+                                 const unsigned char *input,
+                                 unsigned char *output )
+{
+    int ret;
+
+    ret = mbedtls_chacha20_update( ctx, length, input, output );
+    if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    return( ret );
+}
+
+static void * chacha20_ctx_alloc( void )
+{
+    mbedtls_chacha20_context *ctx;
+    ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    mbedtls_chacha20_init( ctx );
+
+    return( ctx );
+}
+
+static void chacha20_ctx_free( void *ctx )
+{
+    mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t chacha20_base_info = {
+    MBEDTLS_CIPHER_ID_CHACHA20,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    chacha20_stream_wrap,
+#endif
+    chacha20_setkey_wrap,
+    chacha20_setkey_wrap,
+    chacha20_ctx_alloc,
+    chacha20_ctx_free
+};
+static const mbedtls_cipher_info_t chacha20_info = {
+    MBEDTLS_CIPHER_CHACHA20,
+    MBEDTLS_MODE_STREAM,
+    256,
+    "CHACHA20",
+    12,
+    0,
+    1,
+    &chacha20_base_info
+};
+#endif /* MBEDTLS_CHACHA20_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+
+static int chachapoly_setkey_wrap( void *ctx,
+                                   const unsigned char *key,
+                                   unsigned int key_bitlen )
+{
+    if( key_bitlen != 256U )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    return( 0 );
+}
+
+static void * chachapoly_ctx_alloc( void )
+{
+    mbedtls_chachapoly_context *ctx;
+    ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    mbedtls_chachapoly_init( ctx );
+
+    return( ctx );
+}
+
+static void chachapoly_ctx_free( void *ctx )
+{
+    mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t chachapoly_base_info = {
+    MBEDTLS_CIPHER_ID_CHACHA20,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    chachapoly_setkey_wrap,
+    chachapoly_setkey_wrap,
+    chachapoly_ctx_alloc,
+    chachapoly_ctx_free
+};
+static const mbedtls_cipher_info_t chachapoly_info = {
+    MBEDTLS_CIPHER_CHACHA20_POLY1305,
+    MBEDTLS_MODE_NONE,
+    256,
+    "CHACHA20-POLY1305",
+    12,
+    0,
+    1,
+    &chachapoly_base_info
+};
+#endif /* MBEDTLS_CHACHAPOLY_C */
+
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
 static int null_crypt_stream( void *ctx, size_t length,
                               const unsigned char *input,
@@ -1322,9 +1709,15 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     null_crypt_stream,
 #endif
@@ -1362,11 +1755,20 @@
     { MBEDTLS_CIPHER_AES_192_CFB128,       &aes_192_cfb128_info },
     { MBEDTLS_CIPHER_AES_256_CFB128,       &aes_256_cfb128_info },
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    { MBEDTLS_CIPHER_AES_128_OFB,          &aes_128_ofb_info },
+    { MBEDTLS_CIPHER_AES_192_OFB,          &aes_192_ofb_info },
+    { MBEDTLS_CIPHER_AES_256_OFB,          &aes_256_ofb_info },
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     { MBEDTLS_CIPHER_AES_128_CTR,          &aes_128_ctr_info },
     { MBEDTLS_CIPHER_AES_192_CTR,          &aes_192_ctr_info },
     { MBEDTLS_CIPHER_AES_256_CTR,          &aes_256_ctr_info },
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    { MBEDTLS_CIPHER_AES_128_XTS,          &aes_128_xts_info },
+    { MBEDTLS_CIPHER_AES_256_XTS,          &aes_256_xts_info },
+#endif
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_CIPHER_AES_128_GCM,          &aes_128_gcm_info },
     { MBEDTLS_CIPHER_AES_192_GCM,          &aes_192_gcm_info },
@@ -1438,6 +1840,14 @@
 #endif
 #endif /* MBEDTLS_DES_C */
 
+#if defined(MBEDTLS_CHACHA20_C)
+    { MBEDTLS_CIPHER_CHACHA20,             &chacha20_info },
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    { MBEDTLS_CIPHER_CHACHA20_POLY1305,    &chachapoly_info },
+#endif
+
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
     { MBEDTLS_CIPHER_NULL,                 &null_cipher_info },
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
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..a3deb86 100644
--- a/library/error.c
+++ b/library/error.c
@@ -69,6 +69,14 @@
 #include "mbedtls/ccm.h"
 #endif
 
+#if defined(MBEDTLS_CHACHA20_C)
+#include "mbedtls/chacha20.h"
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#include "mbedtls/chachapoly.h"
+#endif
+
 #if defined(MBEDTLS_CIPHER_C)
 #include "mbedtls/cipher.h"
 #endif
@@ -101,6 +109,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
@@ -149,6 +161,10 @@
 #include "mbedtls/pkcs5.h"
 #endif
 
+#if defined(MBEDTLS_POLY1305_C)
+#include "mbedtls/poly1305.h"
+#endif
+
 #if defined(MBEDTLS_RIPEMD160_C)
 #include "mbedtls/ripemd160.h"
 #endif
@@ -653,6 +669,24 @@
         mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" );
 #endif /* MBEDTLS_CCM_C */
 
+#if defined(MBEDTLS_CHACHA20_C)
+    if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) )
+        mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" );
+    if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) )
+        mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" );
+#endif /* MBEDTLS_CHACHA20_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA) )
+        mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Invalid input parameter(s)" );
+    if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) )
+        mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" );
+    if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) )
+        mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" );
+    if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_FEATURE_UNAVAILABLE) )
+        mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Feature not available. For example, s part of the API is not implemented" );
+#endif /* MBEDTLS_CHACHAPOLY_C */
+
 #if defined(MBEDTLS_CMAC_C)
     if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) )
         mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" );
@@ -698,6 +732,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" );
@@ -765,6 +804,13 @@
         mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
 #endif /* MBEDTLS_PADLOCK_C */
 
+#if defined(MBEDTLS_POLY1305_C)
+    if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) )
+        mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" );
+    if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) )
+        mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" );
+#endif /* MBEDTLS_POLY1305_C */
+
 #if defined(MBEDTLS_RIPEMD160_C)
     if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) )
         mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" );
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/poly1305.c b/library/poly1305.c
new file mode 100644
index 0000000..a9fff47
--- /dev/null
+++ b/library/poly1305.c
@@ -0,0 +1,534 @@
+/**
+ * \file poly1305.c
+ *
+ * \brief Poly1305 authentication algorithm.
+ *
+ *  Copyright (C) 2006-2016, 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_POLY1305_C)
+
+#if !defined(MBEDTLS_POLY1305_ALT)
+
+#include "mbedtls/poly1305.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#define POLY1305_BLOCK_SIZE_BYTES ( 16U )
+
+#define BYTES_TO_U32_LE( data, offset )                           \
+    ( (uint32_t) data[offset]                                     \
+          | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 )   \
+          | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 )  \
+          | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 )  \
+    )
+
+/* 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;
+}
+
+/**
+ * \brief                   Process blocks with Poly1305.
+ *
+ * \param ctx               The Poly1305 context.
+ * \param nblocks           Number of blocks to process. Note that this function
+ *                          only processes full blocks.
+ * \param input             Buffer containing the input block(s).
+ * \param needs_padding     Set to 0 if the padding bit has already been applied
+ *                          to the input data before calling this function.
+ *                          Otherwise, set this parameter to 1.
+ */
+static void mbedtls_poly1305_process( mbedtls_poly1305_context *ctx,
+                                      size_t nblocks,
+                                      const unsigned char *input,
+                                      uint32_t needs_padding )
+{
+    uint64_t d0, d1, d2, d3;
+    uint32_t acc0, acc1, acc2, acc3, acc4;
+    uint32_t r0, r1, r2, r3;
+    uint32_t rs1, rs2, rs3;
+    size_t offset  = 0U;
+    size_t i;
+
+    r0 = ctx->r[0];
+    r1 = ctx->r[1];
+    r2 = ctx->r[2];
+    r3 = ctx->r[3];
+
+    rs1 = r1 + ( r1 >> 2U );
+    rs2 = r2 + ( r2 >> 2U );
+    rs3 = r3 + ( r3 >> 2U );
+
+    acc0 = ctx->acc[0];
+    acc1 = ctx->acc[1];
+    acc2 = ctx->acc[2];
+    acc3 = ctx->acc[3];
+    acc4 = ctx->acc[4];
+
+    /* Process full blocks */
+    for ( i = 0U; i < nblocks; i++ )
+    {
+        /* Compute: acc += block */
+        /* Note that the input block is treated as a 128-bit little-endian integer */
+        d0   = (uint64_t) acc0 + BYTES_TO_U32_LE( input, offset + 0  );
+        d1   = (uint64_t) acc1 + BYTES_TO_U32_LE( input, offset + 4  ) + ( d0 >> 32U );
+        d2   = (uint64_t) acc2 + BYTES_TO_U32_LE( input, offset + 8  ) + ( d1 >> 32U );
+        d3   = (uint64_t) acc3 + BYTES_TO_U32_LE( input, offset + 12 ) + ( d2 >> 32U );
+        acc0 = (uint32_t) d0;
+        acc1 = (uint32_t) d1;
+        acc2 = (uint32_t) d2;
+        acc3 = (uint32_t) d3;
+        acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding;
+
+        /* Compute: acc *= r */
+        d0 = ( (uint64_t) acc0 * r0  ) +
+             ( (uint64_t) acc1 * rs3 ) +
+             ( (uint64_t) acc2 * rs2 ) +
+             ( (uint64_t) acc3 * rs1 );
+        d1 = ( (uint64_t) acc0 * r1  ) +
+             ( (uint64_t) acc1 * r0  ) +
+             ( (uint64_t) acc2 * rs3 ) +
+             ( (uint64_t) acc3 * rs2 ) +
+             ( (uint64_t) acc4 * rs1 );
+        d2 = ( (uint64_t) acc0 * r2  ) +
+             ( (uint64_t) acc1 * r1  ) +
+             ( (uint64_t) acc2 * r0  ) +
+             ( (uint64_t) acc3 * rs3 ) +
+             ( (uint64_t) acc4 * rs2 );
+        d3 = ( (uint64_t) acc0 * r3  ) +
+             ( (uint64_t) acc1 * r2  ) +
+             ( (uint64_t) acc2 * r1  ) +
+             ( (uint64_t) acc3 * r0  ) +
+             ( (uint64_t) acc4 * rs3 );
+        acc4 *= r0;
+
+        /* Compute: acc %= (2^130 - 5) (partial remainder) */
+        d1 += ( d0 >> 32 );
+        d2 += ( d1 >> 32 );
+        d3 += ( d2 >> 32 );
+        acc0 = (uint32_t) d0;
+        acc1 = (uint32_t) d1;
+        acc2 = (uint32_t) d2;
+        acc3 = (uint32_t) d3;
+        acc4 = (uint32_t) ( d3 >> 32 ) + acc4;
+
+        d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU );
+        acc4 &= 3U;
+        acc0 = (uint32_t) d0;
+        d0 = (uint64_t) acc1 + ( d0 >> 32U );
+        acc1 = (uint32_t) d0;
+        d0 = (uint64_t) acc2 + ( d0 >> 32U );
+        acc2 = (uint32_t) d0;
+        d0 = (uint64_t) acc3 + ( d0 >> 32U );
+        acc3 = (uint32_t) d0;
+        d0 = (uint64_t) acc4 + ( d0 >> 32U );
+        acc4 = (uint32_t) d0;
+
+        offset    += POLY1305_BLOCK_SIZE_BYTES;
+    }
+
+    ctx->acc[0] = acc0;
+    ctx->acc[1] = acc1;
+    ctx->acc[2] = acc2;
+    ctx->acc[3] = acc3;
+    ctx->acc[4] = acc4;
+}
+
+/**
+ * \brief                   Compute the Poly1305 MAC
+ *
+ * \param ctx               The Poly1305 context.
+ * \param mac               The buffer to where the MAC is written. Must be
+ *                          big enough to contain the 16-byte MAC.
+ */
+static void mbedtls_poly1305_compute_mac( const mbedtls_poly1305_context *ctx,
+                                          unsigned char mac[16] )
+{
+    uint64_t d;
+    uint32_t g0, g1, g2, g3, g4;
+    uint32_t acc0, acc1, acc2, acc3, acc4;
+    uint32_t mask;
+    uint32_t mask_inv;
+
+    acc0 = ctx->acc[0];
+    acc1 = ctx->acc[1];
+    acc2 = ctx->acc[2];
+    acc3 = ctx->acc[3];
+    acc4 = ctx->acc[4];
+
+    /* Before adding 's' we need to ensure that the accumulator is mod 2^130 - 5.
+     * We do this by calculating acc - (2^130 - 5), then checking if
+     * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5)
+     */
+
+    /* Calculate acc + -(2^130 - 5) */
+    d  = ( (uint64_t) acc0 + 5U );
+    g0 = (uint32_t) d;
+    d  = ( (uint64_t) acc1 + ( d >> 32 ) );
+    g1 = (uint32_t) d;
+    d  = ( (uint64_t) acc2 + ( d >> 32 ) );
+    g2 = (uint32_t) d;
+    d  = ( (uint64_t) acc3 + ( d >> 32 ) );
+    g3 = (uint32_t) d;
+    g4 = acc4 + (uint32_t) ( d >> 32U );
+
+    /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */
+    mask = (uint32_t) 0U - ( g4 >> 2U );
+    mask_inv = ~mask;
+
+    /* If 131st bit is set then acc=g, otherwise, acc is unmodified */
+    acc0 = ( acc0 & mask_inv ) | ( g0 & mask );
+    acc1 = ( acc1 & mask_inv ) | ( g1 & mask );
+    acc2 = ( acc2 & mask_inv ) | ( g2 & mask );
+    acc3 = ( acc3 & mask_inv ) | ( g3 & mask );
+
+    /* Add 's' */
+    d = (uint64_t) acc0 + ctx->s[0];
+    acc0 = (uint32_t) d;
+    d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U );
+    acc1 = (uint32_t) d;
+    d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U );
+    acc2 = (uint32_t) d;
+    acc3 += ctx->s[3] + (uint32_t) ( d >> 32U );
+
+    /* Compute MAC (128 least significant bits of the accumulator) */
+    mac[0]  = (unsigned char) acc0;
+    mac[1]  = (unsigned char) ( acc0 >> 8  );
+    mac[2]  = (unsigned char) ( acc0 >> 16 );
+    mac[3]  = (unsigned char) ( acc0 >> 24 );
+    mac[4]  = (unsigned char) acc1;
+    mac[5]  = (unsigned char) ( acc1 >> 8  );
+    mac[6]  = (unsigned char) ( acc1 >> 16 );
+    mac[7]  = (unsigned char) ( acc1 >> 24 );
+    mac[8]  = (unsigned char) acc2;
+    mac[9]  = (unsigned char) ( acc2 >> 8  );
+    mac[10] = (unsigned char) ( acc2 >> 16 );
+    mac[11] = (unsigned char) ( acc2 >> 24 );
+    mac[12] = (unsigned char) acc3;
+    mac[13] = (unsigned char) ( acc3 >> 8  );
+    mac[14] = (unsigned char) ( acc3 >> 16 );
+    mac[15] = (unsigned char) ( acc3 >> 24 );
+}
+
+void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx )
+{
+    if ( ctx != NULL )
+    {
+        mbedtls_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
+    }
+}
+
+void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx )
+{
+    if ( ctx != NULL )
+    {
+        mbedtls_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
+    }
+}
+
+int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
+                             const unsigned char key[32] )
+{
+    if ( ctx == NULL || key == NULL )
+    {
+        return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    }
+
+    /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
+    ctx->r[0] = BYTES_TO_U32_LE( key, 0 )  & 0x0FFFFFFFU;
+    ctx->r[1] = BYTES_TO_U32_LE( key, 4 )  & 0x0FFFFFFCU;
+    ctx->r[2] = BYTES_TO_U32_LE( key, 8 )  & 0x0FFFFFFCU;
+    ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU;
+
+    ctx->s[0] = BYTES_TO_U32_LE( key, 16 );
+    ctx->s[1] = BYTES_TO_U32_LE( key, 20 );
+    ctx->s[2] = BYTES_TO_U32_LE( key, 24 );
+    ctx->s[3] = BYTES_TO_U32_LE( key, 28 );
+
+    /* Initial accumulator state */
+    ctx->acc[0] = 0U;
+    ctx->acc[1] = 0U;
+    ctx->acc[2] = 0U;
+    ctx->acc[3] = 0U;
+    ctx->acc[4] = 0U;
+
+    /* Queue initially empty */
+    mbedtls_zeroize( ctx->queue, sizeof( ctx->queue ) );
+    ctx->queue_len = 0U;
+
+    return( 0 );
+}
+
+int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
+                             const unsigned char *input,
+                             size_t ilen )
+{
+    size_t offset    = 0U;
+    size_t remaining = ilen;
+    size_t queue_free_len;
+    size_t nblocks;
+
+    if ( ctx == NULL )
+    {
+        return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    }
+    else if ( ( ilen > 0U ) && ( input == NULL ) )
+    {
+        /* input pointer is allowed to be NULL only if ilen == 0 */
+        return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    }
+
+    if ( ( remaining > 0U ) && ( ctx->queue_len > 0U ) )
+    {
+        queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
+
+        if ( ilen < queue_free_len )
+        {
+            /* Not enough data to complete the block.
+             * Store this data with the other leftovers.
+             */
+            memcpy( &ctx->queue[ctx->queue_len],
+                    input,
+                    ilen );
+
+            ctx->queue_len += ilen;
+
+            remaining = 0U;
+        }
+        else
+        {
+            /* Enough data to produce a complete block */
+            memcpy( &ctx->queue[ctx->queue_len],
+                    input,
+                    queue_free_len );
+
+            ctx->queue_len = 0U;
+
+            mbedtls_poly1305_process( ctx,
+                                      1U,
+                                      ctx->queue,
+                                      1U ); /* add padding bit */
+
+            offset    += queue_free_len;
+            remaining -= queue_free_len;
+        }
+    }
+
+    if ( remaining >= POLY1305_BLOCK_SIZE_BYTES )
+    {
+        nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES;
+
+        mbedtls_poly1305_process( ctx, nblocks, &input[offset], 1U );
+
+        offset += nblocks * POLY1305_BLOCK_SIZE_BYTES;
+        remaining %= POLY1305_BLOCK_SIZE_BYTES;
+    }
+
+    if ( remaining > 0U )
+    {
+        /* Store partial block */
+        ctx->queue_len = remaining;
+        memcpy( ctx->queue, &input[offset], remaining );
+    }
+
+    return( 0 );
+}
+
+int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
+                             unsigned char mac[16] )
+{
+    if ( ( ctx == NULL ) || ( mac == NULL ) )
+    {
+        return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    }
+
+    /* Process any leftover data */
+    if ( ctx->queue_len > 0U )
+    {
+        /* Add padding bit */
+        ctx->queue[ctx->queue_len] = 1U;
+        ctx->queue_len++;
+
+        /* Pad with zeroes */
+        memset( &ctx->queue[ctx->queue_len],
+                0,
+                POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
+
+        mbedtls_poly1305_process( ctx,
+                                  1U,           /* Process 1 block */
+                                  ctx->queue,
+                                  0U );         /* Don't add padding bit (it was just added above) */
+    }
+
+    mbedtls_poly1305_compute_mac( ctx, mac );
+
+    return( 0 );
+}
+
+int mbedtls_poly1305_mac( const unsigned char key[32],
+                          const unsigned char *input,
+                          size_t ilen,
+                          unsigned char mac[16] )
+{
+    mbedtls_poly1305_context ctx;
+    int result;
+
+    mbedtls_poly1305_init( &ctx );
+
+    result = mbedtls_poly1305_starts( &ctx, key );
+    if ( result != 0 )
+        goto cleanup;
+
+    result = mbedtls_poly1305_update( &ctx, input, ilen );
+    if ( result != 0 )
+        goto cleanup;
+
+    result = mbedtls_poly1305_finish( &ctx, mac );
+
+cleanup:
+    mbedtls_poly1305_free( &ctx );
+    return( result );
+}
+
+#endif /* MBEDTLS_POLY1305_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char test_keys[2][32] =
+{
+    {
+        0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
+        0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8,
+        0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
+        0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b
+    },
+    {
+        0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
+        0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
+        0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
+        0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0
+    }
+};
+
+static const unsigned char test_data[2][127] =
+{
+    {
+        0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
+        0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,
+        0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,
+        0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,
+        0x75, 0x70
+    },
+    {
+        0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,
+        0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,
+        0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+        0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,
+        0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,
+        0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,
+        0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,
+        0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+        0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,
+        0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,
+        0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+        0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,
+        0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+        0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,
+        0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,
+        0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e
+    }
+};
+
+static const size_t test_data_len[2] =
+{
+    34U,
+    127U
+};
+
+static const unsigned char test_mac[2][16] =
+{
+    {
+        0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
+        0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9
+    },
+    {
+        0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,
+        0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62
+    }
+};
+
+#define ASSERT( cond, args )            \
+    do                                  \
+    {                                   \
+        if( ! ( cond ) )                \
+        {                               \
+            if( verbose != 0 )          \
+                mbedtls_printf args;    \
+                                        \
+            return( -1 );               \
+        }                               \
+    }                                   \
+    while( 0 )
+
+int mbedtls_poly1305_self_test( int verbose )
+{
+    unsigned char mac[16];
+    unsigned i;
+    int result;
+
+    for( i = 0U; i < 2U; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  Poly1305 test %u ", i );
+
+        result = mbedtls_poly1305_mac( test_keys[i],
+                                       test_data[i],
+                                       test_data_len[i],
+                                       mac );
+        ASSERT( 0 == result, ( "error code: %i\n", result ) );
+
+        ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) );
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_POLY1305_C */
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 a452caf..89eb501 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -84,6 +84,9 @@
 #if defined(MBEDTLS_TIMING_ALT)
     "MBEDTLS_TIMING_ALT",
 #endif /* MBEDTLS_TIMING_ALT */
+#if defined(MBEDTLS_CHACHAPOLY_ALT)
+    "MBEDTLS_CHACHAPOLY_ALT",
+#endif /* MBEDTLS_CHACHAPOLY_ALT */
 #if defined(MBEDTLS_AES_ALT)
     "MBEDTLS_AES_ALT",
 #endif /* MBEDTLS_AES_ALT */
@@ -99,6 +102,9 @@
 #if defined(MBEDTLS_CCM_ALT)
     "MBEDTLS_CCM_ALT",
 #endif /* MBEDTLS_CCM_ALT */
+#if defined(MBEDTLS_CHACHA20_ALT)
+    "MBEDTLS_CHACHA20_ALT",
+#endif /* MBEDTLS_CHACHA20_ALT */
 #if defined(MBEDTLS_CMAC_ALT)
     "MBEDTLS_CMAC_ALT",
 #endif /* MBEDTLS_CMAC_ALT */
@@ -123,6 +129,9 @@
 #if defined(MBEDTLS_MD5_ALT)
     "MBEDTLS_MD5_ALT",
 #endif /* MBEDTLS_MD5_ALT */
+#if defined(MBEDTLS_POLY1305_ALT)
+    "MBEDTLS_POLY1305_ALT",
+#endif /* MBEDTLS_POLY1305_ALT */
 #if defined(MBEDTLS_RIPEMD160_ALT)
     "MBEDTLS_RIPEMD160_ALT",
 #endif /* MBEDTLS_RIPEMD160_ALT */
@@ -246,12 +255,18 @@
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     "MBEDTLS_CIPHER_MODE_CBC",
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    "MBEDTLS_CIPHER_MODE_OFB",
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     "MBEDTLS_CIPHER_MODE_CFB",
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     "MBEDTLS_CIPHER_MODE_CTR",
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    "MBEDTLS_CIPHER_MODE_XTS",
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
     "MBEDTLS_CIPHER_NULL_CIPHER",
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
@@ -510,6 +525,9 @@
 #if defined(MBEDTLS_AES_C)
     "MBEDTLS_AES_C",
 #endif /* MBEDTLS_AES_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    "MBEDTLS_CHACHAPOLY_C",
+#endif /* MBEDTLS_CHACHAPOLY_C */
 #if defined(MBEDTLS_ARC4_C)
     "MBEDTLS_ARC4_C",
 #endif /* MBEDTLS_ARC4_C */
@@ -531,12 +549,18 @@
 #if defined(MBEDTLS_CAMELLIA_C)
     "MBEDTLS_CAMELLIA_C",
 #endif /* MBEDTLS_CAMELLIA_C */
+#if defined(MBEDTLS_CHACHA20_C)
+    "MBEDTLS_CHACHA20_C",
+#endif /* MBEDTLS_CHACHA20_C */
 #if defined(MBEDTLS_CCM_C)
     "MBEDTLS_CCM_C",
 #endif /* MBEDTLS_CCM_C */
 #if defined(MBEDTLS_CERTS_C)
     "MBEDTLS_CERTS_C",
 #endif /* MBEDTLS_CERTS_C */
+#if defined(MBEDTLS_CHACHA20_C)
+    "MBEDTLS_CHACHA20_C",
+#endif /* MBEDTLS_CHACHA20_C */
 #if defined(MBEDTLS_CIPHER_C)
     "MBEDTLS_CIPHER_C",
 #endif /* MBEDTLS_CIPHER_C */
@@ -579,6 +603,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 */
@@ -633,6 +660,9 @@
 #if defined(MBEDTLS_PLATFORM_C)
     "MBEDTLS_PLATFORM_C",
 #endif /* MBEDTLS_PLATFORM_C */
+#if defined(MBEDTLS_POLY1305_C)
+    "MBEDTLS_POLY1305_C",
+#endif /* MBEDTLS_POLY1305_C */
 #if defined(MBEDTLS_RIPEMD160_C)
     "MBEDTLS_RIPEMD160_C",
 #endif /* MBEDTLS_RIPEMD160_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/benchmark.c b/programs/test/benchmark.c
index cecf3e3..98d231a 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -59,9 +59,12 @@
 #include "mbedtls/aes.h"
 #include "mbedtls/blowfish.h"
 #include "mbedtls/camellia.h"
+#include "mbedtls/chacha20.h"
 #include "mbedtls/gcm.h"
 #include "mbedtls/ccm.h"
+#include "mbedtls/chachapoly.h"
 #include "mbedtls/cmac.h"
+#include "mbedtls/poly1305.h"
 #include "mbedtls/havege.h"
 #include "mbedtls/ctr_drbg.h"
 #include "mbedtls/hmac_drbg.h"
@@ -93,8 +96,9 @@
 
 #define OPTIONS                                                         \
     "md4, md5, ripemd160, sha1, sha256, sha512,\n"                      \
-    "arc4, des3, des, camellia, blowfish,\n"                            \
-    "aes_cbc, aes_gcm, aes_ccm, aes_cmac, des3_cmac,\n"                 \
+    "arc4, des3, des, camellia, blowfish, chacha20,\n"                  \
+    "aes_cbc, aes_gcm, aes_ccm, aes_cmac, aes_xts, des3_cmac,\n"        \
+    "chachapoly, poly1305\n"                                            \
     "havege, ctr_drbg, hmac_drbg\n"                                     \
     "rsa, dhm, ecdsa, ecdh.\n"
 
@@ -228,8 +232,10 @@
 typedef struct {
     char md4, md5, ripemd160, sha1, sha256, sha512,
          arc4, des3, des,
-         aes_cbc, aes_gcm, aes_ccm, aes_cmac, des3_cmac,
          camellia, blowfish,
+         chacha20,
+         aes_cbc, aes_gcm, aes_ccm, aes_cmac, aes_xts, des3_cmac,
+         chachapoly, poly1305,
          havege, ctr_drbg, hmac_drbg,
          rsa, dhm, ecdsa, ecdh;
 } todo_list;
@@ -278,14 +284,22 @@
                 todo.aes_gcm = 1;
             else if( strcmp( argv[i], "aes_ccm" ) == 0 )
                 todo.aes_ccm = 1;
+            else if( strcmp( argv[i], "chachapoly" ) == 0 )
+                todo.chachapoly = 1;
             else if( strcmp( argv[i], "aes_cmac" ) == 0 )
                 todo.aes_cmac = 1;
+            else if( strcmp( argv[i], "aes_xts" ) == 0 )
+                todo.aes_xts = 1;
             else if( strcmp( argv[i], "des3_cmac" ) == 0 )
                 todo.des3_cmac = 1;
             else if( strcmp( argv[i], "camellia" ) == 0 )
                 todo.camellia = 1;
             else if( strcmp( argv[i], "blowfish" ) == 0 )
                 todo.blowfish = 1;
+            else if( strcmp( argv[i], "chacha20" ) == 0 )
+                todo.chacha20 = 1;
+            else if( strcmp( argv[i], "poly1305" ) == 0 )
+                todo.poly1305 = 1;
             else if( strcmp( argv[i], "havege" ) == 0 )
                 todo.havege = 1;
             else if( strcmp( argv[i], "ctr_drbg" ) == 0 )
@@ -465,6 +479,27 @@
         }
     }
 #endif
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if( todo.chachapoly )
+    {
+        mbedtls_chachapoly_context chachapoly;
+
+        mbedtls_chachapoly_init( &chachapoly );
+        memset( buf, 0, sizeof( buf ) );
+        memset( tmp, 0, sizeof( tmp ) );
+
+        mbedtls_snprintf( title, sizeof( title ), "ChaCha20-Poly1305" );
+
+        mbedtls_chachapoly_setkey( &chachapoly, tmp );
+
+        TIME_AND_TSC( title,
+                mbedtls_chachapoly_crypt_and_tag( &chachapoly,
+                    MBEDTLS_CHACHAPOLY_ENCRYPT, BUFSIZE, tmp,
+                    NULL, 0, buf, buf, tmp ) );
+
+        mbedtls_chachapoly_free( &chachapoly );
+    }
+#endif
 #if defined(MBEDTLS_CMAC_C)
     if( todo.aes_cmac )
     {
@@ -496,6 +531,29 @@
                                                 output ) );
     }
 #endif /* MBEDTLS_CMAC_C */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    if( todo.aes_xts )
+    {
+        int keysize;
+        mbedtls_aes_xts_context ctx;
+
+        mbedtls_aes_xts_init( &ctx );
+        for( keysize = 128; keysize <= 256; keysize += 64 )
+        {
+            mbedtls_snprintf( title, sizeof( title ), "AES-XTS-%d", keysize );
+
+            memset( buf, 0, sizeof( buf ) );
+            memset( tmp, 0, sizeof( tmp ) );
+            mbedtls_aes_xts_setkey_enc( &ctx, tmp, keysize * 2);
+
+            TIME_AND_TSC( title,
+                    mbedtls_aes_crypt_xts( &ctx, MBEDTLS_AES_ENCRYPT, BUFSIZE,
+                                           tmp, buf, buf ) );
+
+            mbedtls_aes_xts_free( &ctx );
+        }
+    }
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -520,6 +578,20 @@
     }
 #endif
 
+#if defined(MBEDTLS_CHACHA20_C)
+    if ( todo.chacha20 )
+    {
+        TIME_AND_TSC( "ChaCha20", mbedtls_chacha20_crypt( buf, buf, 0U, BUFSIZE, buf, buf ) );
+    }
+#endif
+
+#if defined(MBEDTLS_POLY1305_C)
+    if ( todo.poly1305 )
+    {
+        TIME_AND_TSC( "Poly1305", mbedtls_poly1305_mac( buf, buf, BUFSIZE, buf ) );
+    }
+#endif
+
 #if defined(MBEDTLS_BLOWFISH_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
     if( todo.blowfish )
     {
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 72a3734..13fa98c 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -44,6 +44,9 @@
 #include "mbedtls/des.h"
 #include "mbedtls/aes.h"
 #include "mbedtls/camellia.h"
+#include "mbedtls/chacha20.h"
+#include "mbedtls/poly1305.h"
+#include "mbedtls/chachapoly.h"
 #include "mbedtls/base64.h"
 #include "mbedtls/bignum.h"
 #include "mbedtls/rsa.h"
@@ -207,6 +210,15 @@
 #if defined(MBEDTLS_CMAC_C)
     {"cmac", mbedtls_cmac_self_test},
 #endif
+#if defined(MBEDTLS_CHACHA20_C)
+    {"chacha20", mbedtls_chacha20_self_test},
+#endif
+#if defined(MBEDTLS_POLY1305_C)
+    {"poly1305", mbedtls_poly1305_self_test},
+#endif
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    {"chacha20-poly1305", mbedtls_chachapoly_self_test},
+#endif
 #if defined(MBEDTLS_BASE64_C)
     {"base64", mbedtls_base64_self_test},
 #endif
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..d064889 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -30,9 +30,9 @@
 my $error_format_file = $data_dir.'/error.fmt';
 
 my @low_level_modules = qw( AES ARC4 ASN1 BASE64 BIGNUM BLOWFISH
-                            CAMELLIA CCM CMAC CTR_DRBG DES
-                            ENTROPY GCM HMAC_DRBG MD2 MD4 MD5
-                            NET OID PADLOCK PBKDF2 RIPEMD160
+                            CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES
+                            ENTROPY GCM HKDF HMAC_DRBG MD2 MD4 MD5
+                            NET OID PADLOCK PBKDF2 POLY1305 RIPEMD160
                             SHA1 SHA256 SHA512 THREADING XTEA );
 my @high_level_modules = qw( CIPHER DHM ECP MD
                              PEM PK PKCS12 PKCS5
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..66d60a9 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -54,11 +54,15 @@
 add_test_suite(blowfish)
 add_test_suite(camellia)
 add_test_suite(ccm)
+add_test_suite(chacha20)
+add_test_suite(chachapoly)
 add_test_suite(cipher cipher.aes)
 add_test_suite(cipher cipher.arc4)
 add_test_suite(cipher cipher.blowfish)
 add_test_suite(cipher cipher.camellia)
 add_test_suite(cipher cipher.ccm)
+add_test_suite(cipher cipher.chacha20)
+add_test_suite(cipher cipher.chachapoly)
 add_test_suite(cipher cipher.des)
 add_test_suite(cipher cipher.gcm)
 add_test_suite(cipher cipher.null)
@@ -81,6 +85,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)
@@ -96,6 +101,7 @@
 add_test_suite(pk)
 add_test_suite(pkparse)
 add_test_suite(pkwrite)
+add_test_suite(poly1305)
 add_test_suite(shax)
 add_test_suite(ssl)
 add_test_suite(timing)
diff --git a/tests/Makefile b/tests/Makefile
index d85617f..e47dbaa 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -46,13 +46,18 @@
 endif
 
 APPS =	test_suite_aes.ecb$(EXEXT)	test_suite_aes.cbc$(EXEXT)	\
-	test_suite_aes.cfb$(EXEXT)	test_suite_aes.rest$(EXEXT)	\
+	test_suite_aes.cfb$(EXEXT)	test_suite_aes.ofb$(EXEXT)	\
+	test_suite_aes.xts$(EXEXT)	\
+	test_suite_aes.rest$(EXEXT)	\
 	test_suite_arc4$(EXEXT)		test_suite_asn1write$(EXEXT)	\
 	test_suite_base64$(EXEXT)	test_suite_blowfish$(EXEXT)	\
 	test_suite_camellia$(EXEXT)	test_suite_ccm$(EXEXT)		\
+	test_suite_chacha20$(EXEXT)	test_suite_chachapoly$(EXEXT)	\
 	test_suite_cmac$(EXEXT)						\
+	test_suite_cipher.chachapoly$(EXEXT)				\
 	test_suite_cipher.aes$(EXEXT)					\
 	test_suite_cipher.arc4$(EXEXT)	test_suite_cipher.ccm$(EXEXT)	\
+	test_suite_cipher.chacha20$(EXEXT)				\
 	test_suite_cipher.gcm$(EXEXT)					\
 	test_suite_cipher.blowfish$(EXEXT)				\
 	test_suite_cipher.camellia$(EXEXT)				\
@@ -70,6 +75,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)				\
@@ -81,6 +87,7 @@
 	test_suite_pkcs1_v21$(EXEXT)	test_suite_pkcs5$(EXEXT)	\
 	test_suite_pkparse$(EXEXT)	test_suite_pkwrite$(EXEXT)	\
 	test_suite_pk$(EXEXT)						\
+	test_suite_poly1305$(EXEXT)					\
 	test_suite_rsa$(EXEXT)		test_suite_shax$(EXEXT)		\
 	test_suite_ssl$(EXEXT)		test_suite_timing$(EXEXT)			\
 	test_suite_x509parse$(EXEXT)	test_suite_x509write$(EXEXT)	\
@@ -109,6 +116,14 @@
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_aes test_suite_aes.cfb
 
+test_suite_aes.ofb.c : suites/test_suite_aes.function suites/test_suite_aes.ofb.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo "  Gen   $@"
+	perl scripts/generate_code.pl suites test_suite_aes test_suite_aes.ofb
+
+test_suite_aes.xts.c : suites/test_suite_aes.function suites/test_suite_aes.xts.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo "  Gen   $@"
+	perl scripts/generate_code.pl suites test_suite_aes test_suite_aes.xts
+
 test_suite_aes.rest.c : suites/test_suite_aes.function suites/test_suite_aes.rest.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_aes test_suite_aes.rest
@@ -125,6 +140,14 @@
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.ccm
 
+test_suite_cipher.chacha20.c : suites/test_suite_cipher.function suites/test_suite_cipher.chacha20.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo "  Gen   $@"
+	perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.chacha20
+
+test_suite_cipher.chachapoly.c : suites/test_suite_cipher.function suites/test_suite_cipher.chachapoly.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo "  Gen   $@"
+	perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.chachapoly
+
 test_suite_cipher.gcm.c : suites/test_suite_cipher.function suites/test_suite_cipher.gcm.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.gcm
@@ -177,6 +200,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
@@ -197,6 +224,7 @@
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites $* $*
 
+
 test_suite_aes.ecb$(EXEXT): test_suite_aes.ecb.c $(DEP)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -209,6 +237,14 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test_suite_aes.ofb$(EXEXT): test_suite_aes.ofb.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
+test_suite_aes.xts$(EXEXT): test_suite_aes.xts.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test_suite_aes.rest$(EXEXT): test_suite_aes.rest.c $(DEP)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -237,6 +273,14 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test_suite_chacha20$(EXEXT): test_suite_chacha20.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
+test_suite_chachapoly$(EXEXT): test_suite_chachapoly.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test_suite_cmac$(EXEXT): test_suite_cmac.c $(DEP)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -253,6 +297,14 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test_suite_cipher.chacha20$(EXEXT): test_suite_cipher.chacha20.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
+test_suite_cipher.chachapoly$(EXEXT): test_suite_cipher.chachapoly.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test_suite_cipher.gcm$(EXEXT): test_suite_cipher.gcm.c $(DEP)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -341,6 +393,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 $@
@@ -401,6 +457,10 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test_suite_poly1305$(EXEXT): test_suite_poly1305.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test_suite_rsa$(EXEXT): test_suite_rsa.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_aes.function b/tests/suites/test_suite_aes.function
index c5f0eaa..9a98218 100644
--- a/tests/suites/test_suite_aes.function
+++ b/tests/suites/test_suite_aes.function
@@ -7,6 +7,20 @@
  * END_DEPENDENCIES
  */
 
+#if 0
+/* BEGIN_SUITE_HELPERS depends_on:MBEDTLS_CIPHER_MODE_XTS  */
+static void aes_crypt_xts( char *hex_key_string
+                           char *hex_data_unit_string,
+                           char *hex_src_string, char *hex_dst_string,
+                           int mode)
+{
+    /* XXX Code Review: is this possible? (having a shared helper function for
+     * a test, enabled only when that test is). Would line numbers and test
+     * results look appropriate still or would it be too much indirection? */
+}
+/* END_SUITE_HELPERS */
+#endif
+
 /* BEGIN_CASE */
 void aes_encrypt_ecb( char *hex_key_string, char *hex_src_string,
                       char *hex_dst_string, int setkey_result )
@@ -289,6 +303,148 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_OFB */
+void aes_encrypt_ofb( int fragment_size, char *hex_key_string,
+                        char *hex_iv_string, char *hex_src_string,
+                        char *hex_dst_string )
+{
+    unsigned char key_str[100];
+    unsigned char iv_str[100];
+    unsigned char src_str[200];
+    unsigned char dst_str[200];
+    unsigned char output[200];
+    mbedtls_aes_context ctx;
+    size_t iv_offset = 0;
+    int in_buffer_len;
+    unsigned char* src_str_next;
+    int key_len;
+
+    memset(key_str, 0x00, 100);
+    memset(iv_str, 0x00, 100);
+    memset(src_str, 0x00, 200);
+    memset(dst_str, 0x00, 200);
+    memset(output, 0x00, 200);
+    mbedtls_aes_init( &ctx );
+
+    key_len = unhexify( key_str, hex_key_string );
+    unhexify( iv_str, hex_iv_string );
+    in_buffer_len = unhexify( src_str, hex_src_string );
+
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str, key_len * 8 ) == 0 );
+    src_str_next = src_str;
+
+    while( in_buffer_len > 0 )
+    {
+        TEST_ASSERT( mbedtls_aes_crypt_ofb( &ctx, fragment_size, &iv_offset,
+                                            iv_str, src_str_next, output ) == 0 );
+
+        hexify( dst_str, output, fragment_size );
+        TEST_ASSERT( strncmp( (char *) dst_str, hex_dst_string,
+                                ( 2 * fragment_size) ) == 0 );
+
+        in_buffer_len -= fragment_size;
+        hex_dst_string += ( fragment_size * 2 );
+        src_str_next += fragment_size;
+
+        if( in_buffer_len < fragment_size )
+            fragment_size = in_buffer_len;
+    }
+
+exit:
+    mbedtls_aes_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_XTS */
+void aes_encrypt_xts( char *hex_key_string, char *hex_data_unit_string,
+                      char *hex_src_string, char *hex_dst_string )
+{
+    enum { AES_BLOCK_SIZE = 16 };
+    unsigned char *key;
+    unsigned char *data_unit;
+    unsigned char *src;
+    unsigned char *dst;
+    unsigned char *output;
+    mbedtls_aes_xts_context ctx;
+    size_t key_len, src_len, dst_len, data_unit_len;
+
+    mbedtls_aes_xts_init( &ctx );
+
+    data_unit = unhexify_alloc( hex_data_unit_string, &data_unit_len );
+    TEST_ASSERT( data_unit_len == AES_BLOCK_SIZE );
+
+    key = unhexify_alloc( hex_key_string, &key_len );
+    TEST_ASSERT( key_len % 2 == 0 );
+
+    src = unhexify_alloc( hex_src_string, &src_len );
+    dst = unhexify_alloc( hex_dst_string, &dst_len );
+    TEST_ASSERT( src_len == dst_len );
+
+    output = zero_alloc(dst_len);
+
+    mbedtls_aes_xts_setkey_enc( &ctx, key, key_len * 8 );
+    TEST_ASSERT( mbedtls_aes_crypt_xts( &ctx, MBEDTLS_AES_ENCRYPT, src_len, data_unit, src, output ) == 0 ); // XXX Code Review: must this be one line?
+
+    TEST_ASSERT( memcmp( output, dst, dst_len ) == 0 );
+
+exit:
+    mbedtls_aes_xts_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_XTS */
+void aes_decrypt_xts( char *hex_key_string, char *hex_data_unit_string,
+                      char *hex_dst_string, char *hex_src_string )
+{
+    /* XXX Code Review: I don't really like all this duplicated code between
+     * encrypt and decrypt. The only thing different is the mode and key
+     * initialization. */
+    enum { AES_BLOCK_SIZE = 16 };
+    unsigned char *key;
+    unsigned char *data_unit;
+    unsigned char *src;
+    unsigned char *dst;
+    unsigned char *output;
+    mbedtls_aes_xts_context ctx;
+    size_t key_len, src_len, dst_len, data_unit_len;
+
+    mbedtls_aes_xts_init( &ctx );
+
+    data_unit = unhexify_alloc( hex_data_unit_string, &data_unit_len );
+    TEST_ASSERT( data_unit_len == AES_BLOCK_SIZE );
+
+    key = unhexify_alloc( hex_key_string, &key_len );
+    TEST_ASSERT( key_len % 2 == 0 );
+    src = unhexify_alloc( hex_src_string, &src_len );
+    dst = unhexify_alloc( hex_dst_string, &dst_len );
+    TEST_ASSERT( src_len == dst_len );
+
+    output = zero_alloc(dst_len);
+
+    mbedtls_aes_xts_setkey_dec( &ctx, key, key_len * 8 );
+    TEST_ASSERT( mbedtls_aes_crypt_xts( &ctx, MBEDTLS_AES_DECRYPT, src_len, data_unit, src, output ) == 0 ); // XXX Code Review: must this be one line?
+
+    TEST_ASSERT( memcmp( output, dst, dst_len ) == 0 );
+
+exit:
+    mbedtls_aes_xts_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_XTS */
+void aes_crypt_xts_size( int size, int retval )
+{
+    size_t length = size;
+    /* Note that this function will most likely crash on failure, as NULL
+     * parameters will be used. In the passing case, the length check in
+     * mbedtls_aes_crypt_xts() will prevent any accesses to parameters by
+     * exiting the function early. XXX <-- Hey look, Mr. Codereviewer. What do
+     * you think? Any ideas how to be safe and not have to actually allocate a
+     * 16 MiB buffer nor add NULL checks to mbedtls_aes_crypt_xts()? */
+    TEST_ASSERT( mbedtls_aes_crypt_xts( NULL, MBEDTLS_AES_ENCRYPT, length, NULL, NULL, NULL ) == retval );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
 void aes_selftest()
 {
diff --git a/tests/suites/test_suite_aes.ofb.data b/tests/suites/test_suite_aes.ofb.data
new file mode 100644
index 0000000..4b9d80e
--- /dev/null
+++ b/tests/suites/test_suite_aes.ofb.data
@@ -0,0 +1,35 @@
+# NIST Special Publication 800-38A
+# Recommendation for Block Cipher Modes of Operation
+# Test Vectors - Appendix F, Section F.4
+OFB-AES128.Encrypt - Single block
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"2b7e151628aed2a6abf7158809cf4f3c":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172a":"3b3fd92eb72dad20333449f8e83cfb4a"
+
+OFB-AES128.Encrypt - Partial blocks - 7 bytes
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:5:"2b7e151628aed2a6abf7158809cf4f3c":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":"3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e"
+
+OFB-AES128.Encrypt - Test NIST SP800-38A - F.4.1
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"2b7e151628aed2a6abf7158809cf4f3c":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":"3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e"
+
+OFB-AES128.Decrypt - Test NIST SP800-38A - F.4.2
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"2b7e151628aed2a6abf7158809cf4f3c":"000102030405060708090a0b0c0d0e0f":"3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
+
+OFB-AES192.Encrypt - Test NIST SP800-38A - F.4.3
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":"cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a"
+
+OFB-AES192.Decrypt - Test NIST SP800-38A - F.4.4
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b":"000102030405060708090a0b0c0d0e0f":"cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
+
+OFB-AES256.Encrypt - Test NIST SP800-38A - F.4.5
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":"dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484"
+
+OFB-AES256.Decrypt - Test NIST SP800-38A - F.4.6
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4":"000102030405060708090a0b0c0d0e0f":"dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
+
diff --git a/tests/suites/test_suite_aes.xts.data b/tests/suites/test_suite_aes.xts.data
new file mode 100644
index 0000000..98dd43b
--- /dev/null
+++ b/tests/suites/test_suite_aes.xts.data
@@ -0,0 +1,137 @@
+AES-128-XTS Encrypt Fail Sector Too Small (by 1 byte)
+aes_crypt_xts_size:15:-0x0022
+
+AES-128-XTS Encrypt Fail Sector Too Large (by 1 byte)
+aes_crypt_xts_size:16777217:-0x0022
+
+AES-128-XTS Encrypt Fail Sector Too Large (by 1 block)
+aes_crypt_xts_size:16777232:-0x0022
+
+#
+# IEEE P1619/D16 Annex B Test Vectors
+# http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
+#
+# 128-bit keys with 32 byte sector
+#
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 1
+aes_encrypt_xts:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"0000000000000000000000000000000000000000000000000000000000000000":"917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 2
+aes_encrypt_xts:"1111111111111111111111111111111122222222222222222222222222222222":"33333333330000000000000000000000":"4444444444444444444444444444444444444444444444444444444444444444":"c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 3
+aes_encrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f022222222222222222222222222222222":"33333333330000000000000000000000":"4444444444444444444444444444444444444444444444444444444444444444":"af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89"
+
+#
+# 128-bit keys with 512 byte sector
+#
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 4
+aes_encrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"00000000000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 5
+aes_encrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"01000000000000000000000000000000":"27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568":"264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 6
+aes_encrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"02000000000000000000000000000000":"264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd":"fa762a3680b76007928ed4a4f49a9456031b704782e65e16cecb54ed7d017b5e18abd67b338e81078f21edb7868d901ebe9c731a7c18b5e6dec1d6a72e078ac9a4262f860beefa14f4e821018272e411a951502b6e79066e84252c3346f3aa62344351a291d4bedc7a07618bdea2af63145cc7a4b8d4070691ae890cd65733e7946e9021a1dffc4c59f159425ee6d50ca9b135fa6162cea18a939838dc000fb386fad086acce5ac07cb2ece7fd580b00cfa5e98589631dc25e8e2a3daf2ffdec26531659912c9d8f7a15e5865ea8fb5816d6207052bd7128cd743c12c8118791a4736811935eb982a532349e31dd401e0b660a568cb1a4711f552f55ded59f1f15bf7196b3ca12a91e488ef59d64f3a02bf45239499ac6176ae321c4a211ec545365971c5d3f4f09d4eb139bfdf2073d33180b21002b65cc9865e76cb24cd92c874c24c18350399a936ab3637079295d76c417776b94efce3a0ef7206b15110519655c956cbd8b2489405ee2b09a6b6eebe0c53790a12a8998378b33a5b71159625f4ba49d2a2fdba59fbf0897bc7aabd8d707dc140a80f0f309f835d3da54ab584e501dfa0ee977fec543f74186a802b9a37adb3e8291eca04d66520d229e60401e7282bef486ae059aa70696e0e305d777140a7a883ecdcb69b9ff938e8a4231864c69ca2c2043bed007ff3e605e014bcf518138dc3a25c5e236171a2d01d6"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 7
+aes_encrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"fd000000000000000000000000000000":"8e41b78c390b5af9d758bb214a67e9f6bf7727b09ac6124084c37611398fa45daad94868600ed391fb1acd4857a95b466e62ef9f4b377244d1c152e7b30d731aad30c716d214b707aed99eb5b5e580b3e887cf7497465651d4b60e6042051da3693c3b78c14489543be8b6ad0ba629565bba202313ba7b0d0c94a3252b676f46cc02ce0f8a7d34c0ed229129673c1f61aed579d08a9203a25aac3a77e9db60267996db38df637356d9dcd1632e369939f2a29d89345c66e05066f1a3677aef18dea4113faeb629e46721a66d0a7e785d3e29af2594eb67dfa982affe0aac058f6e15864269b135418261fc3afb089472cf68c45dd7f231c6249ba0255e1e033833fc4d00a3fe02132d7bc3873614b8aee34273581ea0325c81f0270affa13641d052d36f0757d484014354d02d6883ca15c24d8c3956b1bd027bcf41f151fd8023c5340e5606f37e90fdb87c86fb4fa634b3718a30bace06a66eaf8f63c4aa3b637826a87fe8cfa44282e92cb1615af3a28e53bc74c7cba1a0977be9065d0c1a5dec6c54ae38d37f37aa35283e048e5530a85c4e7a29d7b92ec0c3169cdf2a805c7604bce60049b9fb7b8eaac10f51ae23794ceba68bb58112e293b9b692ca721b37c662f8574ed4dba6f88e170881c82cddc1034a0ca7e284bf0962b6b26292d836fa9f73c1ac770eef0f2d3a1eaf61d3e03555fd424eedd67e18a18094f888":"d55f684f81f4426e9fde92a5ff02df2ac896af63962888a97910c1379e20b0a3b1db613fb7fe2e07004329ea5c22bfd33e3dbe4cf58cc608c2c26c19a2e2fe22f98732c2b5cb844cc6c0702d91e1d50fc4382a7eba5635cd602432a2306ac4ce82f8d70c8d9bc15f918fe71e74c622d5cf71178bf6e0b9cc9f2b41dd8dbe441c41cd0c73a6dc47a348f6702f9d0e9b1b1431e948e299b9ec2272ab2c5f0c7be86affa5dec87a0bee81d3d50007edaa2bcfccb35605155ff36ed8edd4a40dcd4b243acd11b2b987bdbfaf91a7cac27e9c5aea525ee53de7b2d3332c8644402b823e94a7db26276d2d23aa07180f76b4fd29b9c0823099c9d62c519880aee7e9697617c1497d47bf3e571950311421b6b734d38b0db91eb85331b91ea9f61530f54512a5a52a4bad589eb69781d537f23297bb459bdad2948a29e1550bf4787e0be95bb173cf5fab17dab7a13a052a63453d97ccec1a321954886b7a1299faaeecae35c6eaaca753b041b5e5f093bf83397fd21dd6b3012066fcc058cc32c3b09d7562dee29509b5839392c9ff05f51f3166aaac4ac5f238038a3045e6f72e48ef0fe8bc675e82c318a268e43970271bf119b81bf6a982746554f84e72b9f00280a320a08142923c23c883423ff949827f29bbacdc1ccdb04938ce6098c95ba6b32528f4ef78eed778b2e122ddfd1cbdd11d1c0a6783e011fc536d63d053260637"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 8
+aes_encrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"fe000000000000000000000000000000":"d55f684f81f4426e9fde92a5ff02df2ac896af63962888a97910c1379e20b0a3b1db613fb7fe2e07004329ea5c22bfd33e3dbe4cf58cc608c2c26c19a2e2fe22f98732c2b5cb844cc6c0702d91e1d50fc4382a7eba5635cd602432a2306ac4ce82f8d70c8d9bc15f918fe71e74c622d5cf71178bf6e0b9cc9f2b41dd8dbe441c41cd0c73a6dc47a348f6702f9d0e9b1b1431e948e299b9ec2272ab2c5f0c7be86affa5dec87a0bee81d3d50007edaa2bcfccb35605155ff36ed8edd4a40dcd4b243acd11b2b987bdbfaf91a7cac27e9c5aea525ee53de7b2d3332c8644402b823e94a7db26276d2d23aa07180f76b4fd29b9c0823099c9d62c519880aee7e9697617c1497d47bf3e571950311421b6b734d38b0db91eb85331b91ea9f61530f54512a5a52a4bad589eb69781d537f23297bb459bdad2948a29e1550bf4787e0be95bb173cf5fab17dab7a13a052a63453d97ccec1a321954886b7a1299faaeecae35c6eaaca753b041b5e5f093bf83397fd21dd6b3012066fcc058cc32c3b09d7562dee29509b5839392c9ff05f51f3166aaac4ac5f238038a3045e6f72e48ef0fe8bc675e82c318a268e43970271bf119b81bf6a982746554f84e72b9f00280a320a08142923c23c883423ff949827f29bbacdc1ccdb04938ce6098c95ba6b32528f4ef78eed778b2e122ddfd1cbdd11d1c0a6783e011fc536d63d053260637":"72efc1ebfe1ee25975a6eb3aa8589dda2b261f1c85bdab442a9e5b2dd1d7c3957a16fc08e526d4b1223f1b1232a11af274c3d70dac57f83e0983c498f1a6f1aecb021c3e70085a1e527f1ce41ee5911a82020161529cd82773762daf5459de94a0a82adae7e1703c808543c29ed6fb32d9e004327c1355180c995a07741493a09c21ba01a387882da4f62534b87bb15d60d197201c0fd3bf30c1500a3ecfecdd66d8721f90bcc4c17ee925c61b0a03727a9c0d5f5ca462fbfa0af1c2513a9d9d4b5345bd27a5f6e653f751693e6b6a2b8ead57d511e00e58c45b7b8d005af79288f5c7c22fd4f1bf7a898b03a5634c6a1ae3f9fae5de4f296a2896b23e7ed43ed14fa5a2803f4d28f0d3ffcf24757677aebdb47bb388378708948a8d4126ed1839e0da29a537a8c198b3c66ab00712dd261674bf45a73d67f76914f830ca014b65596f27e4cf62de66125a5566df9975155628b400fbfb3a29040ed50faffdbb18aece7c5c44693260aab386c0a37b11b114f1c415aebb653be468179428d43a4d8bc3ec38813eca30a13cf1bb18d524f1992d44d8b1a42ea30b22e6c95b199d8d182f8840b09d059585c31ad691fa0619ff038aca2c39a943421157361717c49d322028a74648113bd8c9d7ec77cf3c89c1ec8718ceff8516d96b34c3c614f10699c9abc4ed0411506223bea16af35c883accdbe1104eef0cfdb54e12fb230a"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 9
+aes_encrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"ff000000000000000000000000000000":"72efc1ebfe1ee25975a6eb3aa8589dda2b261f1c85bdab442a9e5b2dd1d7c3957a16fc08e526d4b1223f1b1232a11af274c3d70dac57f83e0983c498f1a6f1aecb021c3e70085a1e527f1ce41ee5911a82020161529cd82773762daf5459de94a0a82adae7e1703c808543c29ed6fb32d9e004327c1355180c995a07741493a09c21ba01a387882da4f62534b87bb15d60d197201c0fd3bf30c1500a3ecfecdd66d8721f90bcc4c17ee925c61b0a03727a9c0d5f5ca462fbfa0af1c2513a9d9d4b5345bd27a5f6e653f751693e6b6a2b8ead57d511e00e58c45b7b8d005af79288f5c7c22fd4f1bf7a898b03a5634c6a1ae3f9fae5de4f296a2896b23e7ed43ed14fa5a2803f4d28f0d3ffcf24757677aebdb47bb388378708948a8d4126ed1839e0da29a537a8c198b3c66ab00712dd261674bf45a73d67f76914f830ca014b65596f27e4cf62de66125a5566df9975155628b400fbfb3a29040ed50faffdbb18aece7c5c44693260aab386c0a37b11b114f1c415aebb653be468179428d43a4d8bc3ec38813eca30a13cf1bb18d524f1992d44d8b1a42ea30b22e6c95b199d8d182f8840b09d059585c31ad691fa0619ff038aca2c39a943421157361717c49d322028a74648113bd8c9d7ec77cf3c89c1ec8718ceff8516d96b34c3c614f10699c9abc4ed0411506223bea16af35c883accdbe1104eef0cfdb54e12fb230a":"3260ae8dad1f4a32c5cafe3ab0eb95549d461a67ceb9e5aa2d3afb62dece0553193ba50c75be251e08d1d08f1088576c7efdfaaf3f459559571e12511753b07af073f35da06af0ce0bbf6b8f5ccc5cea500ec1b211bd51f63b606bf6528796ca12173ba39b8935ee44ccce646f90a45bf9ccc567f0ace13dc2d53ebeedc81f58b2e41179dddf0d5a5c42f5d8506c1a5d2f8f59f3ea873cbcd0eec19acbf325423bd3dcb8c2b1bf1d1eaed0eba7f0698e4314fbeb2f1566d1b9253008cbccf45a2b0d9c5c9c21474f4076e02be26050b99dee4fd68a4cf890e496e4fcae7b70f94ea5a9062da0daeba1993d2ccd1dd3c244b8428801495a58b216547e7e847c46d1d756377b6242d2e5fb83bf752b54e0df71e889f3a2bb0f4c10805bf3c590376e3c24e22ff57f7fa965577375325cea5d920db94b9c336b455f6e894c01866fe9fbb8c8d3f70a2957285f6dfb5dcd8cbf54782f8fe7766d4723819913ac773421e3a31095866bad22c86a6036b2518b2059b4229d18c8c2ccbdf906c6cc6e82464ee57bddb0bebcb1dc645325bfb3e665ef7251082c88ebb1cf203bd779fdd38675713c8daadd17e1cabee432b09787b6ddf3304e38b731b45df5df51b78fcfb3d32466028d0ba36555e7e11ab0ee0666061d1645d962444bc47a38188930a84b4d561395c73c087021927ca638b7afc8a8679ccb84c26555440ec7f10445cd"
+
+#
+# 256-bit keys with 512 byte sector
+#
+AES-256-XTS Encrypt IEEE P1619/D16 Vector 10
+aes_encrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ff000000000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151"
+
+AES-256-XTS Encrypt IEEE P1619/D16 Vector 11
+aes_encrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ffff0000000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"77a31251618a15e6b92d1d66dffe7b50b50bad552305ba0217a610688eff7e11e1d0225438e093242d6db274fde801d4cae06f2092c728b2478559df58e837c2469ee4a4fa794e4bbc7f39bc026e3cb72c33b0888f25b4acf56a2a9804f1ce6d3d6e1dc6ca181d4b546179d55544aa7760c40d06741539c7e3cd9d2f6650b2013fd0eeb8c2b8e3d8d240ccae2d4c98320a7442e1c8d75a42d6e6cfa4c2eca1798d158c7aecdf82490f24bb9b38e108bcda12c3faf9a21141c3613b58367f922aaa26cd22f23d708dae699ad7cb40a8ad0b6e2784973dcb605684c08b8d6998c69aac049921871ebb65301a4619ca80ecb485a31d744223ce8ddc2394828d6a80470c092f5ba413c3378fa6054255c6f9df4495862bbb3287681f931b687c888abf844dfc8fc28331e579928cd12bd2390ae123cf03818d14dedde5c0c24c8ab018bfca75ca096f2d531f3d1619e785f1ada437cab92e980558b3dce1474afb75bfedbf8ff54cb2618e0244c9ac0d3c66fb51598cd2db11f9be39791abe447c63094f7c453b7ff87cb5bb36b7c79efb0872d17058b83b15ab0866ad8a58656c5a7e20dbdf308b2461d97c0ec0024a2715055249cf3b478ddd4740de654f75ca686e0d7345c69ed50cdc2a8b332b1f8824108ac937eb050585608ee734097fc09054fbff89eeaeea791f4a7ab1f9868294a4f9e27b42af8100cb9d59cef9645803"
+
+AES-256-XTS Encrypt IEEE P1619/D16 Vector 12
+aes_encrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ffffff00000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"e387aaa58ba483afa7e8eb469778317ecf4cf573aa9d4eac23f2cdf914e4e200a8b490e42ee646802dc6ee2b471b278195d60918ececb44bf79966f83faba0499298ebc699c0c8634715a320bb4f075d622e74c8c932004f25b41e361025b5a87815391f6108fc4afa6a05d9303c6ba68a128a55705d415985832fdeaae6c8e19110e84d1b1f199a2692119edc96132658f09da7c623efcec712537a3d94c0bf5d7e352ec94ae5797fdb377dc1551150721adf15bd26a8efc2fcaad56881fa9e62462c28f30ae1ceaca93c345cf243b73f542e2074a705bd2643bb9f7cc79bb6e7091ea6e232df0f9ad0d6cf502327876d82207abf2115cdacf6d5a48f6c1879a65b115f0f8b3cb3c59d15dd8c769bc014795a1837f3901b5845eb491adfefe097b1fa30a12fc1f65ba22905031539971a10f2f36c321bb51331cdefb39e3964c7ef079994f5b69b2edd83a71ef549971ee93f44eac3938fcdd61d01fa71799da3a8091c4c48aa9ed263ff0749df95d44fef6a0bb578ec69456aa5408ae32c7af08ad7ba8921287e3bbee31b767be06a0e705c864a769137df28292283ea81a2480241b44d9921cdbec1bc28dc1fda114bd8e5217ac9d8ebafa720e9da4f9ace231cc949e5b96fe76ffc21063fddc83a6b8679c00d35e09576a875305bed5f36ed242c8900dd1fa965bc950dfce09b132263a1eef52dd6888c309f5a7d712826"
+
+AES-256-XTS Encrypt IEEE P1619/D16 Vector 13
+aes_encrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ffffffff000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"bf53d2dade78e822a4d949a9bc6766b01b06a8ef70d26748c6a7fc36d80ae4c5520f7c4ab0ac8544424fa405162fef5a6b7f229498063618d39f0003cb5fb8d1c86b643497da1ff945c8d3bedeca4f479702a7a735f043ddb1d6aaade3c4a0ac7ca7f3fa5279bef56f82cd7a2f38672e824814e10700300a055e1630b8f1cb0e919f5e942010a416e2bf48cb46993d3cb6a51c19bacf864785a00bc2ecff15d350875b246ed53e68be6f55bd7e05cfc2b2ed6432198a6444b6d8c247fab941f569768b5c429366f1d3f00f0345b96123d56204c01c63b22ce78baf116e525ed90fdea39fa469494d3866c31e05f295ff21fea8d4e6e13d67e47ce722e9698a1c1048d68ebcde76b86fcf976eab8aa9790268b7068e017a8b9b749409514f1053027fd16c3786ea1bac5f15cb79711ee2abe82f5cf8b13ae73030ef5b9e4457e75d1304f988d62dd6fc4b94ed38ba831da4b7634971b6cd8ec325d9c61c00f1df73627ed3745a5e8489f3a95c69639c32cd6e1d537a85f75cc844726e8a72fc0077ad22000f1d5078f6b866318c668f1ad03d5a5fced5219f2eabbd0aa5c0f460d183f04404a0d6f469558e81fab24a167905ab4c7878502ad3e38fdbe62a41556cec37325759533ce8f25f367c87bb5578d667ae93f9e2fd99bcbc5f2fbba88cf6516139420fcff3b7361d86322c4bd84c82f335abb152c4a93411373aaa8220"
+
+AES-256-XTS Encrypt IEEE P1619/D16 Vector 14
+aes_encrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ffffffffff0000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"64497e5a831e4a932c09be3e5393376daa599548b816031d224bbf50a818ed2350eae7e96087c8a0db51ad290bd00c1ac1620857635bf246c176ab463be30b808da548081ac847b158e1264be25bb0910bbc92647108089415d45fab1b3d2604e8a8eff1ae4020cfa39936b66827b23f371b92200be90251e6d73c5f86de5fd4a950781933d79a28272b782a2ec313efdfcc0628f43d744c2dc2ff3dcb66999b50c7ca895b0c64791eeaa5f29499fb1c026f84ce5b5c72ba1083cddb5ce45434631665c333b60b11593fb253c5179a2c8db813782a004856a1653011e93fb6d876c18366dd8683f53412c0c180f9c848592d593f8609ca736317d356e13e2bff3a9f59cd9aeb19cd482593d8c46128bb32423b37a9adfb482b99453fbe25a41bf6feb4aa0bef5ed24bf73c762978025482c13115e4015aac992e5613a3b5c2f685b84795cb6e9b2656d8c88157e52c42f978d8634c43d06fea928f2822e465aa6576e9bf419384506cc3ce3c54ac1a6f67dc66f3b30191e698380bc999b05abce19dc0c6dcc2dd001ec535ba18deb2df1a101023108318c75dc98611a09dc48a0acdec676fabdf222f07e026f059b672b56e5cbc8e1d21bbd867dd927212054681d70ea737134cdfce93b6f82ae22423274e58a0821cc5502e2d0ab4585e94de6975be5e0b4efce51cd3e70c25a1fbbbd609d273ad5b0d59631c531f6a0a57b9"
+
+#
+# 128-bit keys with sector size not evenly divisible by 16 bytes
+#
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 15
+aes_encrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0":"9a785634120000000000000000000000":"000102030405060708090a0b0c0d0e0f10":"6c1625db4671522d3d7599601de7ca09ed"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 16
+aes_encrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0":"9a785634120000000000000000000000":"000102030405060708090a0b0c0d0e0f1011":"d069444b7a7e0cab09e24447d24deb1fedbf"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 17
+aes_encrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0":"9a785634120000000000000000000000":"000102030405060708090a0b0c0d0e0f101112":"e5df1351c0544ba1350b3363cd8ef4beedbf9d"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 18
+aes_encrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0":"9a785634120000000000000000000000":"000102030405060708090a0b0c0d0e0f10111213":"9d84c813f719aa2c7be3f66171c7c5c2edbf9dac"
+
+AES-128-XTS Encrypt IEEE P1619/D16 Vector 19
+aes_encrypt_xts:"e0e1e2e3e4e5e6e7e8e9eaebecedeeefc0c1c2c3c4c5c6c7c8c9cacbcccdcecf":"21436587a90000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"38b45812ef43a05bd957e545907e223b954ab4aaf088303ad910eadf14b42be68b2461149d8c8ba85f992be970bc621f1b06573f63e867bf5875acafa04e42ccbd7bd3c2a0fb1fff791ec5ec36c66ae4ac1e806d81fbf709dbe29e471fad38549c8e66f5345d7c1eb94f405d1ec785cc6f6a68f6254dd8339f9d84057e01a17741990482999516b5611a38f41bb6478e6f173f320805dd71b1932fc333cb9ee39936beea9ad96fa10fb4112b901734ddad40bc1878995f8e11aee7d141a2f5d48b7a4e1e7f0b2c04830e69a4fd1378411c2f287edf48c6c4e5c247a19680f7fe41cefbd49b582106e3616cbbe4dfb2344b2ae9519391f3e0fb4922254b1d6d2d19c6d4d537b3a26f3bcc51588b32f3eca0829b6a5ac72578fb814fb43cf80d64a233e3f997a3f02683342f2b33d25b492536b93becb2f5e1a8b82f5b883342729e8ae09d16938841a21a97fb543eea3bbff59f13c1a18449e398701c1ad51648346cbc04c27bb2da3b93a1372ccae548fb53bee476f9e9c91773b1bb19828394d55d3e1a20ed69113a860b6829ffa847224604435070221b257e8dff783615d2cae4803a93aa4334ab482a0afac9c0aeda70b45a481df5dec5df8cc0f423c77a5fd46cd312021d4b438862419a791be03bb4d97c0e59578542531ba466a83baf92cefc151b5cc1611a167893819b63fb8a6b18e86de60290fa72b797b0ce59f3"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 1
+aes_decrypt_xts:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"0000000000000000000000000000000000000000000000000000000000000000":"917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 2
+aes_decrypt_xts:"1111111111111111111111111111111122222222222222222222222222222222":"33333333330000000000000000000000":"4444444444444444444444444444444444444444444444444444444444444444":"c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 3
+aes_decrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"00000000000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 4
+aes_decrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"00000000000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 5
+aes_decrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"01000000000000000000000000000000":"27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568":"264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 6
+aes_decrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"02000000000000000000000000000000":"264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd":"fa762a3680b76007928ed4a4f49a9456031b704782e65e16cecb54ed7d017b5e18abd67b338e81078f21edb7868d901ebe9c731a7c18b5e6dec1d6a72e078ac9a4262f860beefa14f4e821018272e411a951502b6e79066e84252c3346f3aa62344351a291d4bedc7a07618bdea2af63145cc7a4b8d4070691ae890cd65733e7946e9021a1dffc4c59f159425ee6d50ca9b135fa6162cea18a939838dc000fb386fad086acce5ac07cb2ece7fd580b00cfa5e98589631dc25e8e2a3daf2ffdec26531659912c9d8f7a15e5865ea8fb5816d6207052bd7128cd743c12c8118791a4736811935eb982a532349e31dd401e0b660a568cb1a4711f552f55ded59f1f15bf7196b3ca12a91e488ef59d64f3a02bf45239499ac6176ae321c4a211ec545365971c5d3f4f09d4eb139bfdf2073d33180b21002b65cc9865e76cb24cd92c874c24c18350399a936ab3637079295d76c417776b94efce3a0ef7206b15110519655c956cbd8b2489405ee2b09a6b6eebe0c53790a12a8998378b33a5b71159625f4ba49d2a2fdba59fbf0897bc7aabd8d707dc140a80f0f309f835d3da54ab584e501dfa0ee977fec543f74186a802b9a37adb3e8291eca04d66520d229e60401e7282bef486ae059aa70696e0e305d777140a7a883ecdcb69b9ff938e8a4231864c69ca2c2043bed007ff3e605e014bcf518138dc3a25c5e236171a2d01d6"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 7
+aes_decrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"fd000000000000000000000000000000":"8e41b78c390b5af9d758bb214a67e9f6bf7727b09ac6124084c37611398fa45daad94868600ed391fb1acd4857a95b466e62ef9f4b377244d1c152e7b30d731aad30c716d214b707aed99eb5b5e580b3e887cf7497465651d4b60e6042051da3693c3b78c14489543be8b6ad0ba629565bba202313ba7b0d0c94a3252b676f46cc02ce0f8a7d34c0ed229129673c1f61aed579d08a9203a25aac3a77e9db60267996db38df637356d9dcd1632e369939f2a29d89345c66e05066f1a3677aef18dea4113faeb629e46721a66d0a7e785d3e29af2594eb67dfa982affe0aac058f6e15864269b135418261fc3afb089472cf68c45dd7f231c6249ba0255e1e033833fc4d00a3fe02132d7bc3873614b8aee34273581ea0325c81f0270affa13641d052d36f0757d484014354d02d6883ca15c24d8c3956b1bd027bcf41f151fd8023c5340e5606f37e90fdb87c86fb4fa634b3718a30bace06a66eaf8f63c4aa3b637826a87fe8cfa44282e92cb1615af3a28e53bc74c7cba1a0977be9065d0c1a5dec6c54ae38d37f37aa35283e048e5530a85c4e7a29d7b92ec0c3169cdf2a805c7604bce60049b9fb7b8eaac10f51ae23794ceba68bb58112e293b9b692ca721b37c662f8574ed4dba6f88e170881c82cddc1034a0ca7e284bf0962b6b26292d836fa9f73c1ac770eef0f2d3a1eaf61d3e03555fd424eedd67e18a18094f888":"d55f684f81f4426e9fde92a5ff02df2ac896af63962888a97910c1379e20b0a3b1db613fb7fe2e07004329ea5c22bfd33e3dbe4cf58cc608c2c26c19a2e2fe22f98732c2b5cb844cc6c0702d91e1d50fc4382a7eba5635cd602432a2306ac4ce82f8d70c8d9bc15f918fe71e74c622d5cf71178bf6e0b9cc9f2b41dd8dbe441c41cd0c73a6dc47a348f6702f9d0e9b1b1431e948e299b9ec2272ab2c5f0c7be86affa5dec87a0bee81d3d50007edaa2bcfccb35605155ff36ed8edd4a40dcd4b243acd11b2b987bdbfaf91a7cac27e9c5aea525ee53de7b2d3332c8644402b823e94a7db26276d2d23aa07180f76b4fd29b9c0823099c9d62c519880aee7e9697617c1497d47bf3e571950311421b6b734d38b0db91eb85331b91ea9f61530f54512a5a52a4bad589eb69781d537f23297bb459bdad2948a29e1550bf4787e0be95bb173cf5fab17dab7a13a052a63453d97ccec1a321954886b7a1299faaeecae35c6eaaca753b041b5e5f093bf83397fd21dd6b3012066fcc058cc32c3b09d7562dee29509b5839392c9ff05f51f3166aaac4ac5f238038a3045e6f72e48ef0fe8bc675e82c318a268e43970271bf119b81bf6a982746554f84e72b9f00280a320a08142923c23c883423ff949827f29bbacdc1ccdb04938ce6098c95ba6b32528f4ef78eed778b2e122ddfd1cbdd11d1c0a6783e011fc536d63d053260637"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 8
+aes_decrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"fe000000000000000000000000000000":"d55f684f81f4426e9fde92a5ff02df2ac896af63962888a97910c1379e20b0a3b1db613fb7fe2e07004329ea5c22bfd33e3dbe4cf58cc608c2c26c19a2e2fe22f98732c2b5cb844cc6c0702d91e1d50fc4382a7eba5635cd602432a2306ac4ce82f8d70c8d9bc15f918fe71e74c622d5cf71178bf6e0b9cc9f2b41dd8dbe441c41cd0c73a6dc47a348f6702f9d0e9b1b1431e948e299b9ec2272ab2c5f0c7be86affa5dec87a0bee81d3d50007edaa2bcfccb35605155ff36ed8edd4a40dcd4b243acd11b2b987bdbfaf91a7cac27e9c5aea525ee53de7b2d3332c8644402b823e94a7db26276d2d23aa07180f76b4fd29b9c0823099c9d62c519880aee7e9697617c1497d47bf3e571950311421b6b734d38b0db91eb85331b91ea9f61530f54512a5a52a4bad589eb69781d537f23297bb459bdad2948a29e1550bf4787e0be95bb173cf5fab17dab7a13a052a63453d97ccec1a321954886b7a1299faaeecae35c6eaaca753b041b5e5f093bf83397fd21dd6b3012066fcc058cc32c3b09d7562dee29509b5839392c9ff05f51f3166aaac4ac5f238038a3045e6f72e48ef0fe8bc675e82c318a268e43970271bf119b81bf6a982746554f84e72b9f00280a320a08142923c23c883423ff949827f29bbacdc1ccdb04938ce6098c95ba6b32528f4ef78eed778b2e122ddfd1cbdd11d1c0a6783e011fc536d63d053260637":"72efc1ebfe1ee25975a6eb3aa8589dda2b261f1c85bdab442a9e5b2dd1d7c3957a16fc08e526d4b1223f1b1232a11af274c3d70dac57f83e0983c498f1a6f1aecb021c3e70085a1e527f1ce41ee5911a82020161529cd82773762daf5459de94a0a82adae7e1703c808543c29ed6fb32d9e004327c1355180c995a07741493a09c21ba01a387882da4f62534b87bb15d60d197201c0fd3bf30c1500a3ecfecdd66d8721f90bcc4c17ee925c61b0a03727a9c0d5f5ca462fbfa0af1c2513a9d9d4b5345bd27a5f6e653f751693e6b6a2b8ead57d511e00e58c45b7b8d005af79288f5c7c22fd4f1bf7a898b03a5634c6a1ae3f9fae5de4f296a2896b23e7ed43ed14fa5a2803f4d28f0d3ffcf24757677aebdb47bb388378708948a8d4126ed1839e0da29a537a8c198b3c66ab00712dd261674bf45a73d67f76914f830ca014b65596f27e4cf62de66125a5566df9975155628b400fbfb3a29040ed50faffdbb18aece7c5c44693260aab386c0a37b11b114f1c415aebb653be468179428d43a4d8bc3ec38813eca30a13cf1bb18d524f1992d44d8b1a42ea30b22e6c95b199d8d182f8840b09d059585c31ad691fa0619ff038aca2c39a943421157361717c49d322028a74648113bd8c9d7ec77cf3c89c1ec8718ceff8516d96b34c3c614f10699c9abc4ed0411506223bea16af35c883accdbe1104eef0cfdb54e12fb230a"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 9
+aes_decrypt_xts:"2718281828459045235360287471352631415926535897932384626433832795":"ff000000000000000000000000000000":"72efc1ebfe1ee25975a6eb3aa8589dda2b261f1c85bdab442a9e5b2dd1d7c3957a16fc08e526d4b1223f1b1232a11af274c3d70dac57f83e0983c498f1a6f1aecb021c3e70085a1e527f1ce41ee5911a82020161529cd82773762daf5459de94a0a82adae7e1703c808543c29ed6fb32d9e004327c1355180c995a07741493a09c21ba01a387882da4f62534b87bb15d60d197201c0fd3bf30c1500a3ecfecdd66d8721f90bcc4c17ee925c61b0a03727a9c0d5f5ca462fbfa0af1c2513a9d9d4b5345bd27a5f6e653f751693e6b6a2b8ead57d511e00e58c45b7b8d005af79288f5c7c22fd4f1bf7a898b03a5634c6a1ae3f9fae5de4f296a2896b23e7ed43ed14fa5a2803f4d28f0d3ffcf24757677aebdb47bb388378708948a8d4126ed1839e0da29a537a8c198b3c66ab00712dd261674bf45a73d67f76914f830ca014b65596f27e4cf62de66125a5566df9975155628b400fbfb3a29040ed50faffdbb18aece7c5c44693260aab386c0a37b11b114f1c415aebb653be468179428d43a4d8bc3ec38813eca30a13cf1bb18d524f1992d44d8b1a42ea30b22e6c95b199d8d182f8840b09d059585c31ad691fa0619ff038aca2c39a943421157361717c49d322028a74648113bd8c9d7ec77cf3c89c1ec8718ceff8516d96b34c3c614f10699c9abc4ed0411506223bea16af35c883accdbe1104eef0cfdb54e12fb230a":"3260ae8dad1f4a32c5cafe3ab0eb95549d461a67ceb9e5aa2d3afb62dece0553193ba50c75be251e08d1d08f1088576c7efdfaaf3f459559571e12511753b07af073f35da06af0ce0bbf6b8f5ccc5cea500ec1b211bd51f63b606bf6528796ca12173ba39b8935ee44ccce646f90a45bf9ccc567f0ace13dc2d53ebeedc81f58b2e41179dddf0d5a5c42f5d8506c1a5d2f8f59f3ea873cbcd0eec19acbf325423bd3dcb8c2b1bf1d1eaed0eba7f0698e4314fbeb2f1566d1b9253008cbccf45a2b0d9c5c9c21474f4076e02be26050b99dee4fd68a4cf890e496e4fcae7b70f94ea5a9062da0daeba1993d2ccd1dd3c244b8428801495a58b216547e7e847c46d1d756377b6242d2e5fb83bf752b54e0df71e889f3a2bb0f4c10805bf3c590376e3c24e22ff57f7fa965577375325cea5d920db94b9c336b455f6e894c01866fe9fbb8c8d3f70a2957285f6dfb5dcd8cbf54782f8fe7766d4723819913ac773421e3a31095866bad22c86a6036b2518b2059b4229d18c8c2ccbdf906c6cc6e82464ee57bddb0bebcb1dc645325bfb3e665ef7251082c88ebb1cf203bd779fdd38675713c8daadd17e1cabee432b09787b6ddf3304e38b731b45df5df51b78fcfb3d32466028d0ba36555e7e11ab0ee0666061d1645d962444bc47a38188930a84b4d561395c73c087021927ca638b7afc8a8679ccb84c26555440ec7f10445cd"
+
+AES-256-XTS Decrypt IEEE P1619/D16 Vector 10
+aes_decrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ff000000000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151"
+
+AES-256-XTS Decrypt IEEE P1619/D16 Vector 11
+aes_decrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ffff0000000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"77a31251618a15e6b92d1d66dffe7b50b50bad552305ba0217a610688eff7e11e1d0225438e093242d6db274fde801d4cae06f2092c728b2478559df58e837c2469ee4a4fa794e4bbc7f39bc026e3cb72c33b0888f25b4acf56a2a9804f1ce6d3d6e1dc6ca181d4b546179d55544aa7760c40d06741539c7e3cd9d2f6650b2013fd0eeb8c2b8e3d8d240ccae2d4c98320a7442e1c8d75a42d6e6cfa4c2eca1798d158c7aecdf82490f24bb9b38e108bcda12c3faf9a21141c3613b58367f922aaa26cd22f23d708dae699ad7cb40a8ad0b6e2784973dcb605684c08b8d6998c69aac049921871ebb65301a4619ca80ecb485a31d744223ce8ddc2394828d6a80470c092f5ba413c3378fa6054255c6f9df4495862bbb3287681f931b687c888abf844dfc8fc28331e579928cd12bd2390ae123cf03818d14dedde5c0c24c8ab018bfca75ca096f2d531f3d1619e785f1ada437cab92e980558b3dce1474afb75bfedbf8ff54cb2618e0244c9ac0d3c66fb51598cd2db11f9be39791abe447c63094f7c453b7ff87cb5bb36b7c79efb0872d17058b83b15ab0866ad8a58656c5a7e20dbdf308b2461d97c0ec0024a2715055249cf3b478ddd4740de654f75ca686e0d7345c69ed50cdc2a8b332b1f8824108ac937eb050585608ee734097fc09054fbff89eeaeea791f4a7ab1f9868294a4f9e27b42af8100cb9d59cef9645803"
+
+AES-256-XTS Decrypt IEEE P1619/D16 Vector 12
+aes_decrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ffffff00000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"e387aaa58ba483afa7e8eb469778317ecf4cf573aa9d4eac23f2cdf914e4e200a8b490e42ee646802dc6ee2b471b278195d60918ececb44bf79966f83faba0499298ebc699c0c8634715a320bb4f075d622e74c8c932004f25b41e361025b5a87815391f6108fc4afa6a05d9303c6ba68a128a55705d415985832fdeaae6c8e19110e84d1b1f199a2692119edc96132658f09da7c623efcec712537a3d94c0bf5d7e352ec94ae5797fdb377dc1551150721adf15bd26a8efc2fcaad56881fa9e62462c28f30ae1ceaca93c345cf243b73f542e2074a705bd2643bb9f7cc79bb6e7091ea6e232df0f9ad0d6cf502327876d82207abf2115cdacf6d5a48f6c1879a65b115f0f8b3cb3c59d15dd8c769bc014795a1837f3901b5845eb491adfefe097b1fa30a12fc1f65ba22905031539971a10f2f36c321bb51331cdefb39e3964c7ef079994f5b69b2edd83a71ef549971ee93f44eac3938fcdd61d01fa71799da3a8091c4c48aa9ed263ff0749df95d44fef6a0bb578ec69456aa5408ae32c7af08ad7ba8921287e3bbee31b767be06a0e705c864a769137df28292283ea81a2480241b44d9921cdbec1bc28dc1fda114bd8e5217ac9d8ebafa720e9da4f9ace231cc949e5b96fe76ffc21063fddc83a6b8679c00d35e09576a875305bed5f36ed242c8900dd1fa965bc950dfce09b132263a1eef52dd6888c309f5a7d712826"
+
+AES-256-XTS Decrypt IEEE P1619/D16 Vector 13
+aes_decrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ffffffff000000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"bf53d2dade78e822a4d949a9bc6766b01b06a8ef70d26748c6a7fc36d80ae4c5520f7c4ab0ac8544424fa405162fef5a6b7f229498063618d39f0003cb5fb8d1c86b643497da1ff945c8d3bedeca4f479702a7a735f043ddb1d6aaade3c4a0ac7ca7f3fa5279bef56f82cd7a2f38672e824814e10700300a055e1630b8f1cb0e919f5e942010a416e2bf48cb46993d3cb6a51c19bacf864785a00bc2ecff15d350875b246ed53e68be6f55bd7e05cfc2b2ed6432198a6444b6d8c247fab941f569768b5c429366f1d3f00f0345b96123d56204c01c63b22ce78baf116e525ed90fdea39fa469494d3866c31e05f295ff21fea8d4e6e13d67e47ce722e9698a1c1048d68ebcde76b86fcf976eab8aa9790268b7068e017a8b9b749409514f1053027fd16c3786ea1bac5f15cb79711ee2abe82f5cf8b13ae73030ef5b9e4457e75d1304f988d62dd6fc4b94ed38ba831da4b7634971b6cd8ec325d9c61c00f1df73627ed3745a5e8489f3a95c69639c32cd6e1d537a85f75cc844726e8a72fc0077ad22000f1d5078f6b866318c668f1ad03d5a5fced5219f2eabbd0aa5c0f460d183f04404a0d6f469558e81fab24a167905ab4c7878502ad3e38fdbe62a41556cec37325759533ce8f25f367c87bb5578d667ae93f9e2fd99bcbc5f2fbba88cf6516139420fcff3b7361d86322c4bd84c82f335abb152c4a93411373aaa8220"
+
+AES-256-XTS Decrypt IEEE P1619/D16 Vector 14
+aes_decrypt_xts:"27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592":"ffffffffff0000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"64497e5a831e4a932c09be3e5393376daa599548b816031d224bbf50a818ed2350eae7e96087c8a0db51ad290bd00c1ac1620857635bf246c176ab463be30b808da548081ac847b158e1264be25bb0910bbc92647108089415d45fab1b3d2604e8a8eff1ae4020cfa39936b66827b23f371b92200be90251e6d73c5f86de5fd4a950781933d79a28272b782a2ec313efdfcc0628f43d744c2dc2ff3dcb66999b50c7ca895b0c64791eeaa5f29499fb1c026f84ce5b5c72ba1083cddb5ce45434631665c333b60b11593fb253c5179a2c8db813782a004856a1653011e93fb6d876c18366dd8683f53412c0c180f9c848592d593f8609ca736317d356e13e2bff3a9f59cd9aeb19cd482593d8c46128bb32423b37a9adfb482b99453fbe25a41bf6feb4aa0bef5ed24bf73c762978025482c13115e4015aac992e5613a3b5c2f685b84795cb6e9b2656d8c88157e52c42f978d8634c43d06fea928f2822e465aa6576e9bf419384506cc3ce3c54ac1a6f67dc66f3b30191e698380bc999b05abce19dc0c6dcc2dd001ec535ba18deb2df1a101023108318c75dc98611a09dc48a0acdec676fabdf222f07e026f059b672b56e5cbc8e1d21bbd867dd927212054681d70ea737134cdfce93b6f82ae22423274e58a0821cc5502e2d0ab4585e94de6975be5e0b4efce51cd3e70c25a1fbbbd609d273ad5b0d59631c531f6a0a57b9"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 15
+aes_decrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0":"9a785634120000000000000000000000":"000102030405060708090a0b0c0d0e0f10":"6c1625db4671522d3d7599601de7ca09ed"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 16
+aes_decrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0":"9a785634120000000000000000000000":"000102030405060708090a0b0c0d0e0f1011":"d069444b7a7e0cab09e24447d24deb1fedbf"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 17
+aes_decrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0":"9a785634120000000000000000000000":"000102030405060708090a0b0c0d0e0f101112":"e5df1351c0544ba1350b3363cd8ef4beedbf9d"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 18
+aes_decrypt_xts:"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0":"9a785634120000000000000000000000":"000102030405060708090a0b0c0d0e0f10111213":"9d84c813f719aa2c7be3f66171c7c5c2edbf9dac"
+
+AES-128-XTS Decrypt IEEE P1619/D16 Vector 19
+aes_decrypt_xts:"e0e1e2e3e4e5e6e7e8e9eaebecedeeefc0c1c2c3c4c5c6c7c8c9cacbcccdcecf":"21436587a90000000000000000000000":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"38b45812ef43a05bd957e545907e223b954ab4aaf088303ad910eadf14b42be68b2461149d8c8ba85f992be970bc621f1b06573f63e867bf5875acafa04e42ccbd7bd3c2a0fb1fff791ec5ec36c66ae4ac1e806d81fbf709dbe29e471fad38549c8e66f5345d7c1eb94f405d1ec785cc6f6a68f6254dd8339f9d84057e01a17741990482999516b5611a38f41bb6478e6f173f320805dd71b1932fc333cb9ee39936beea9ad96fa10fb4112b901734ddad40bc1878995f8e11aee7d141a2f5d48b7a4e1e7f0b2c04830e69a4fd1378411c2f287edf48c6c4e5c247a19680f7fe41cefbd49b582106e3616cbbe4dfb2344b2ae9519391f3e0fb4922254b1d6d2d19c6d4d537b3a26f3bcc51588b32f3eca0829b6a5ac72578fb814fb43cf80d64a233e3f997a3f02683342f2b33d25b492536b93becb2f5e1a8b82f5b883342729e8ae09d16938841a21a97fb543eea3bbff59f13c1a18449e398701c1ad51648346cbc04c27bb2da3b93a1372ccae548fb53bee476f9e9c91773b1bb19828394d55d3e1a20ed69113a860b6829ffa847224604435070221b257e8dff783615d2cae4803a93aa4334ab482a0afac9c0aeda70b45a481df5dec5df8cc0f423c77a5fd46cd312021d4b438862419a791be03bb4d97c0e59578542531ba466a83baf92cefc151b5cc1611a167893819b63fb8a6b18e86de60290fa72b797b0ce59f3"
diff --git a/tests/suites/test_suite_chacha20.data b/tests/suites/test_suite_chacha20.data
new file mode 100644
index 0000000..3f9033e
--- /dev/null
+++ b/tests/suites/test_suite_chacha20.data
@@ -0,0 +1,29 @@
+ChaCha20 RFC 7539 Example and Test Vector (Encrypt)
+chacha20_crypt:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f":"000000000000004a00000000":1:"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":"6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d"
+
+ChaCha20 RFC 7539 Example and Test Vector (Decrypt)
+chacha20_crypt:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f":"000000000000004a00000000":1:"6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e"
+
+ChaCha20 RFC 7539 Test Vector #1 (Encrypt)
+chacha20_crypt:"0000000000000000000000000000000000000000000000000000000000000000":"000000000000000000000000":0:"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586"
+
+ChaCha20 RFC 7539 Test Vector #1 (Decrypt)
+chacha20_crypt:"0000000000000000000000000000000000000000000000000000000000000000":"000000000000000000000000":0:"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+
+ChaCha20 RFC 7539 Test Vector #2 (Encrypt)
+chacha20_crypt:"0000000000000000000000000000000000000000000000000000000000000001":"000000000000000000000002":1:"416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f":"a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d4b7955ec2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f56e031ca5eb6250d4042e02785ececfa4b4bb5e8ead0440e20b6e8db09d881a7c6132f420e52795042bdfa7773d8a9051447b3291ce1411c680465552aa6c405b7764d5e87bea85ad00f8449ed8f72d0d662ab052691ca66424bc86d2df80ea41f43abf937d3259dc4b2d0dfb48a6c9139ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b0871cdac638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6ccc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e818b04b0bc39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80ef2554d7189c411f5869ca52c5b83fa36ff216b9c1d30062bebcfd2dc5bce0911934fda79a86f6e698ced759c3ff9b6477338f3da4f9cd8514ea9982ccafb341b2384dd902f3d1ab7ac61dd29c6f21ba5b862f3730e37cfdc4fd806c22f221"
+
+ChaCha20 RFC 7539 Test Vector #2 (Decrypt)
+chacha20_crypt:"0000000000000000000000000000000000000000000000000000000000000001":"000000000000000000000002":1:"a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d4b7955ec2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f56e031ca5eb6250d4042e02785ececfa4b4bb5e8ead0440e20b6e8db09d881a7c6132f420e52795042bdfa7773d8a9051447b3291ce1411c680465552aa6c405b7764d5e87bea85ad00f8449ed8f72d0d662ab052691ca66424bc86d2df80ea41f43abf937d3259dc4b2d0dfb48a6c9139ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b0871cdac638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6ccc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e818b04b0bc39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80ef2554d7189c411f5869ca52c5b83fa36ff216b9c1d30062bebcfd2dc5bce0911934fda79a86f6e698ced759c3ff9b6477338f3da4f9cd8514ea9982ccafb341b2384dd902f3d1ab7ac61dd29c6f21ba5b862f3730e37cfdc4fd806c22f221":"416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f"
+
+ChaCha20 RFC 7539 Test Vector #3 (Encrypt)
+chacha20_crypt:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"000000000000000000000002":42:"2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e":"62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf166d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f60553ebf39c6402c42234e32a356b3e764312a61a5532055716ead6962568f87d3f3f7704c6a8d1bcd1bf4d50d6154b6da731b187b58dfd728afa36757a797ac188d1"
+
+ChaCha20 RFC 7539 Test Vector #3 (Decrypt)
+chacha20_crypt:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"000000000000000000000002":42:"62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf166d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f60553ebf39c6402c42234e32a356b3e764312a61a5532055716ead6962568f87d3f3f7704c6a8d1bcd1bf4d50d6154b6da731b187b58dfd728afa36757a797ac188d1":"2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e"
+
+ChaCha20 Paremeter Validation
+chacha20_bad_params:
+
+ChaCha20 Selftest
+chacha20_self_test:
diff --git a/tests/suites/test_suite_chacha20.function b/tests/suites/test_suite_chacha20.function
new file mode 100644
index 0000000..669d91e
--- /dev/null
+++ b/tests/suites/test_suite_chacha20.function
@@ -0,0 +1,140 @@
+/* BEGIN_HEADER */
+#include "mbedtls/chacha20.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_CHACHA20_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void chacha20_crypt( char *hex_key_string,
+                     char *hex_nonce_string,
+                     int counter,
+                     char *hex_src_string,
+                     char *hex_dst_string )
+{
+    unsigned char key_str[32]; /* size set by the standard */
+    unsigned char nonce_str[12]; /* size set by the standard */
+    unsigned char src_str[375]; /* max size of binary input */
+    unsigned char dst_str[751]; /* hex expansion of the above */
+    unsigned char output[751];
+    size_t key_len;
+    size_t nonce_len;
+    size_t src_len;
+    size_t dst_len;
+    mbedtls_chacha20_context ctx;
+
+    memset( key_str,    0x00, sizeof( key_str ) );
+    memset( nonce_str,  0x00, sizeof( nonce_str ) );
+    memset( src_str,    0x00, sizeof( src_str ) );
+    memset( dst_str,    0x00, sizeof( dst_str ) );
+    memset( output,     0x00, sizeof( output ) );
+
+    key_len   = unhexify( key_str, hex_key_string );
+    nonce_len = unhexify( nonce_str, hex_nonce_string );
+    src_len   = unhexify( src_str, hex_src_string );
+    dst_len   = unhexify( dst_str, hex_dst_string );
+
+    TEST_ASSERT( src_len   == dst_len );
+    TEST_ASSERT( key_len   == 32U );
+    TEST_ASSERT( nonce_len == 12U );
+
+    /*
+     * Test the integrated API
+     */
+    TEST_ASSERT( mbedtls_chacha20_crypt( key_str, nonce_str, counter, src_len, src_str, output ) == 0 );
+
+    hexify( dst_str, output, src_len );
+    TEST_ASSERT( strcmp( (char*) dst_str, hex_dst_string ) == 0 );
+
+    /*
+     * Test the streaming API
+     */
+    mbedtls_chacha20_init( &ctx );
+
+    TEST_ASSERT( mbedtls_chacha20_setkey( &ctx, key_str ) == 0 );
+
+    TEST_ASSERT( mbedtls_chacha20_starts( &ctx, nonce_str, counter ) == 0 );
+
+    memset( output, 0x00, sizeof( output ) );
+    TEST_ASSERT( mbedtls_chacha20_update( &ctx, src_len, src_str, output ) == 0 );
+
+    hexify( dst_str, output, src_len );
+    TEST_ASSERT( strcmp( (char*) dst_str, hex_dst_string ) == 0 );
+
+    /*
+     * Test the streaming API again, piecewise
+     */
+
+    /* Don't free/init the context nor set the key again,
+     * in order to test that starts() does the right thing. */
+    TEST_ASSERT( mbedtls_chacha20_starts( &ctx, nonce_str, counter ) == 0 );
+
+    memset( output, 0x00, sizeof( output ) );
+    TEST_ASSERT( mbedtls_chacha20_update( &ctx, 1, src_str, output ) == 0 );
+    TEST_ASSERT( mbedtls_chacha20_update( &ctx, src_len - 1, src_str + 1, output + 1 ) == 0 );
+
+    hexify( dst_str, output, src_len );
+    TEST_ASSERT( strcmp( (char*) dst_str, hex_dst_string ) == 0 );
+
+    mbedtls_chacha20_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void chacha20_bad_params()
+{
+    unsigned char key[32];
+    unsigned char nonce[12];
+    unsigned char src[1];
+    unsigned char dst[1];
+    uint32_t counter = 0;
+    size_t len = sizeof( src );
+    mbedtls_chacha20_context ctx;
+
+    mbedtls_chacha20_init( NULL );
+    mbedtls_chacha20_free( NULL );
+
+    mbedtls_chacha20_init( &ctx );
+
+    TEST_ASSERT( mbedtls_chacha20_setkey( NULL, key )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_setkey( &ctx, NULL )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chacha20_starts( NULL, nonce, counter )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_starts( &ctx, NULL, counter )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chacha20_update( NULL, 0, src, dst )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_update( &ctx, len, NULL, dst )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_update( &ctx, len, src, NULL )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_update( &ctx, 0, NULL, NULL )
+                 == 0 );
+
+    mbedtls_chacha20_free( &ctx );
+
+    TEST_ASSERT( mbedtls_chacha20_crypt( NULL, nonce, counter, 0, src, dst )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_crypt( key, NULL, counter, 0, src, dst )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_crypt( key, nonce, counter, len, NULL, dst )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_crypt( key, nonce, counter, len, src, NULL )
+                 == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chacha20_crypt( key, nonce, counter, 0, NULL, NULL )
+                 == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
+void chacha20_self_test()
+{
+    TEST_ASSERT( mbedtls_chacha20_self_test( 1 ) == 0 );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_chachapoly.data b/tests/suites/test_suite_chachapoly.data
new file mode 100644
index 0000000..34cb568
--- /dev/null
+++ b/tests/suites/test_suite_chachapoly.data
@@ -0,0 +1,27 @@
+ChaCha20-Poly1305 RFC 7539 Example and Test Vector (Encrypt)
+mbedtls_chachapoly_enc:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116":"1ae10b594f09e26a7e902ecbd0600691"
+
+ChaCha20-Poly1305 RFC 7539 Example and Test Vector (Decrypt)
+mbedtls_chachapoly_dec:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":"1ae10b594f09e26a7e902ecbd0600691":0
+
+ChaCha20-Poly1305 RFC 7539 Example and Test Vector (Decrypt, not authentic)
+mbedtls_chachapoly_dec:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":"1ae10b594f09e26a7e902ecbd0600690":MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED
+
+ChaCha20-Poly1305 RFC 7539 Test Vector #1 (Encrypt)
+mbedtls_chachapoly_enc:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"000000000102030405060708":"f33388860000000000004e91":"496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d":"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b":"eead9d67890cbb22392336fea1851f38"
+
+ChaCha20-Poly1305 RFC 7539 Test Vector #1 (Decrypt)
+mbedtls_chachapoly_dec:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"000000000102030405060708":"f33388860000000000004e91":"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b":"496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d":"eead9d67890cbb22392336fea1851f38":0
+
+ChaCha20-Poly1305 RFC 7539 Test Vector #1 (Decrypt, not authentic)
+mbedtls_chachapoly_dec:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"000000000102030405060708":"f33388860000000000004e91":"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b":"496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d":"fead9d67890cbb22392336fea1851f38":MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED
+
+ChaCha20-Poly1305 State Flow
+chachapoly_state:
+
+ChaCha20-Poly1305 Parameter Validation
+chachapoly_bad_params:
+
+ChaCha20-Poly1305 Selftest
+depends_on:MBEDTLS_SELF_TEST
+chachapoly_selftest:
diff --git a/tests/suites/test_suite_chachapoly.function b/tests/suites/test_suite_chachapoly.function
new file mode 100644
index 0000000..e379309
--- /dev/null
+++ b/tests/suites/test_suite_chachapoly.function
@@ -0,0 +1,356 @@
+/* BEGIN_HEADER */
+#include "mbedtls/chachapoly.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_CHACHAPOLY_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void mbedtls_chachapoly_enc( char *hex_key_string, char *hex_nonce_string, char *hex_aad_string, char *hex_input_string, char *hex_output_string, char *hex_mac_string )
+{
+    unsigned char key_str[32]; /* size set by the standard */
+    unsigned char nonce_str[12]; /* size set by the standard */
+    unsigned char aad_str[12]; /* max size of test data so far */
+    unsigned char input_str[265]; /* max size of binary input/output so far */
+    unsigned char output_str[265];
+    unsigned char output[265];
+    unsigned char mac_str[16]; /* size set by the standard */
+    unsigned char mac[16]; /* size set by the standard */
+    size_t input_len;
+    size_t output_len;
+    size_t aad_len;
+    size_t key_len;
+    size_t nonce_len;
+    size_t mac_len;
+    mbedtls_chachapoly_context ctx;
+
+    memset( key_str,    0x00, sizeof( key_str ) );
+    memset( nonce_str,  0x00, sizeof( nonce_str ) );
+    memset( aad_str,    0x00, sizeof( aad_str ) );
+    memset( input_str,  0x00, sizeof( input_str ) );
+    memset( output_str, 0x00, sizeof( output_str ) );
+    memset( mac_str,    0x00, sizeof( mac_str ) );
+
+    aad_len    = unhexify( aad_str,    hex_aad_string    );
+    input_len  = unhexify( input_str,  hex_input_string  );
+    output_len = unhexify( output_str, hex_output_string );
+    key_len    = unhexify( key_str,    hex_key_string    );
+    nonce_len  = unhexify( nonce_str,  hex_nonce_string  );
+    mac_len    = unhexify( mac_str,    hex_mac_string    );
+
+    TEST_ASSERT( key_len   == 32 );
+    TEST_ASSERT( nonce_len == 12 );
+    TEST_ASSERT( mac_len   == 16 );
+
+    mbedtls_chachapoly_init( &ctx );
+
+    TEST_ASSERT( mbedtls_chachapoly_setkey( &ctx, key_str ) == 0 );
+
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      input_len, nonce_str,
+                                      aad_str, aad_len,
+                                      input_str, output, mac ) == 0 );
+
+    TEST_ASSERT( memcmp( output_str, output, output_len ) == 0 );
+    TEST_ASSERT( memcmp( mac_str, mac, 16U ) == 0 );
+
+exit:
+    mbedtls_chachapoly_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_chachapoly_dec( char *hex_key_string, char *hex_nonce_string, char *hex_aad_string, char *hex_input_string, char *hex_output_string, char *hex_mac_string, int ret_exp )
+{
+    unsigned char key_str[32]; /* size set by the standard */
+    unsigned char nonce_str[12]; /* size set by the standard */
+    unsigned char aad_str[12]; /* max size of test data so far */
+    unsigned char input_str[265]; /* max size of binary input/output so far */
+    unsigned char output_str[265];
+    unsigned char output[265];
+    unsigned char mac_str[16]; /* size set by the standard */
+    size_t input_len;
+    size_t output_len;
+    size_t aad_len;
+    size_t key_len;
+    size_t nonce_len;
+    size_t mac_len;
+    int ret;
+    mbedtls_chachapoly_context ctx;
+
+    memset( key_str,    0x00, sizeof( key_str ) );
+    memset( nonce_str,  0x00, sizeof( nonce_str ) );
+    memset( aad_str,    0x00, sizeof( aad_str ) );
+    memset( input_str,  0x00, sizeof( input_str ) );
+    memset( output_str, 0x00, sizeof( output_str ) );
+    memset( mac_str,    0x00, sizeof( mac_str ) );
+
+    aad_len    = unhexify( aad_str,    hex_aad_string    );
+    input_len  = unhexify( input_str,  hex_input_string  );
+    output_len = unhexify( output_str, hex_output_string );
+    key_len    = unhexify( key_str,    hex_key_string    );
+    nonce_len  = unhexify( nonce_str,  hex_nonce_string  );
+    mac_len    = unhexify( mac_str,    hex_mac_string    );
+
+    TEST_ASSERT( key_len   == 32 );
+    TEST_ASSERT( nonce_len == 12 );
+    TEST_ASSERT( mac_len   == 16 );
+
+    mbedtls_chachapoly_init( &ctx );
+
+    TEST_ASSERT( mbedtls_chachapoly_setkey( &ctx, key_str ) == 0 );
+
+    ret = mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           input_len, nonce_str,
+                                           aad_str, aad_len,
+                                           mac_str, input_str, output );
+
+    TEST_ASSERT( ret == ret_exp );
+    if( ret_exp == 0 )
+    {
+        TEST_ASSERT( memcmp( output_str, output, output_len ) == 0 );
+    }
+
+exit:
+    mbedtls_chachapoly_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void chachapoly_bad_params()
+{
+    unsigned char key[32];
+    unsigned char nonce[12];
+    unsigned char aad[1];
+    unsigned char input[1];
+    unsigned char output[1];
+    unsigned char mac[16];
+    size_t input_len = sizeof( input );
+    size_t aad_len = sizeof( aad );
+    mbedtls_chachapoly_context ctx;
+
+    memset( key,    0x00, sizeof( key ) );
+    memset( nonce,  0x00, sizeof( nonce ) );
+    memset( aad,    0x00, sizeof( aad ) );
+    memset( input,  0x00, sizeof( input ) );
+    memset( output, 0x00, sizeof( output ) );
+    memset( mac,    0x00, sizeof( mac ) );
+
+    mbedtls_chachapoly_init( NULL );
+    mbedtls_chachapoly_free( NULL );
+
+    mbedtls_chachapoly_init( &ctx );
+
+    TEST_ASSERT( mbedtls_chachapoly_setkey( NULL, key )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_setkey( &ctx, NULL )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( NULL,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      0, nonce,
+                                      aad, 0,
+                                      input, output, mac )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      0, NULL,
+                                      aad, 0,
+                                      input, output, mac )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      0, nonce,
+                                      NULL, aad_len,
+                                      input, output, mac )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      input_len, nonce,
+                                      aad, 0,
+                                      NULL, output, mac )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      input_len, nonce,
+                                      aad, 0,
+                                      input, NULL, mac )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      0, nonce,
+                                      aad, 0,
+                                      input, output, NULL )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( NULL,
+                                           0, nonce,
+                                           aad, 0,
+                                           mac, input, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           0, NULL,
+                                           aad, 0,
+                                           mac, input, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           0, nonce,
+                                           NULL, aad_len,
+                                           mac, input, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           0, nonce,
+                                           aad, 0,
+                                           NULL, input, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           input_len, nonce,
+                                           aad, 0,
+                                           mac, NULL, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           input_len, nonce,
+                                           aad, 0,
+                                           mac, input, NULL )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      0, nonce,
+                                      aad, aad_len,
+                                      NULL, NULL, mac )
+                 == 0 );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           0, nonce,
+                                           aad, aad_len,
+                                           mac, NULL, NULL )
+                 == 0 );
+
+    TEST_ASSERT( mbedtls_chachapoly_crypt_and_tag( &ctx,
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      input_len, nonce,
+                                      NULL, 0,
+                                      input, output, mac )
+                 == 0 );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           input_len, nonce,
+                                           NULL, 0,
+                                           mac, input, output )
+                 == 0 );
+
+    TEST_ASSERT( mbedtls_chachapoly_starts( NULL, nonce, MBEDTLS_CHACHAPOLY_ENCRYPT )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_starts( &ctx, NULL, MBEDTLS_CHACHAPOLY_ENCRYPT )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( NULL, aad, aad_len )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( &ctx, NULL, aad_len )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_update( NULL, input_len, input, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, NULL, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, input, NULL )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_finish( NULL, mac )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_finish( &ctx, NULL )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_INPUT_DATA );
+
+exit:
+    mbedtls_chachapoly_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void chachapoly_state()
+{
+    unsigned char key[32];
+    unsigned char nonce[12];
+    unsigned char aad[1];
+    unsigned char input[1];
+    unsigned char output[1];
+    unsigned char mac[16];
+    size_t input_len = sizeof( input );
+    size_t aad_len = sizeof( aad );
+    mbedtls_chachapoly_context ctx;
+
+    memset( key,    0x00, sizeof( key ) );
+    memset( nonce,  0x00, sizeof( nonce ) );
+    memset( aad,    0x00, sizeof( aad ) );
+    memset( input,  0x00, sizeof( input ) );
+    memset( output, 0x00, sizeof( output ) );
+    memset( mac,    0x00, sizeof( mac ) );
+
+    /* Initial state: finish, update, update_aad forbidden */
+    mbedtls_chachapoly_init( &ctx );
+
+    TEST_ASSERT( mbedtls_chachapoly_finish( &ctx, mac )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, input, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( &ctx, aad, aad_len )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+
+    /* Still initial state: finish, update, update_aad forbidden */
+    TEST_ASSERT( mbedtls_chachapoly_setkey( &ctx, key )
+                 == 0 );
+
+    TEST_ASSERT( mbedtls_chachapoly_finish( &ctx, mac )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, input, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( &ctx, aad, aad_len )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+
+    /* Starts -> finish OK */
+    TEST_ASSERT( mbedtls_chachapoly_starts( &ctx, nonce, MBEDTLS_CHACHAPOLY_ENCRYPT )
+                 == 0 );
+    TEST_ASSERT( mbedtls_chachapoly_finish( &ctx, mac )
+                 == 0 );
+
+    /* After finish: update, update_aad forbidden */
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, input, output )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( &ctx, aad, aad_len )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+
+    /* Starts -> update* OK */
+    TEST_ASSERT( mbedtls_chachapoly_starts( &ctx, nonce, MBEDTLS_CHACHAPOLY_ENCRYPT )
+                 == 0 );
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, input, output )
+                 == 0 );
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, input, output )
+                 == 0 );
+
+    /* After update: update_aad forbidden */
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( &ctx, aad, aad_len )
+                 == MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+
+    /* Starts -> update_aad* -> finish OK */
+    TEST_ASSERT( mbedtls_chachapoly_starts( &ctx, nonce, MBEDTLS_CHACHAPOLY_ENCRYPT )
+                 == 0 );
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( &ctx, aad, aad_len )
+                 == 0 );
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( &ctx, aad, aad_len )
+                 == 0 );
+    TEST_ASSERT( mbedtls_chachapoly_finish( &ctx, mac )
+                 == 0 );
+
+exit:
+    mbedtls_chachapoly_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
+void chachapoly_selftest()
+{
+    TEST_ASSERT( mbedtls_chachapoly_self_test( 1 ) == 0 );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data
index e8e9a15..f212fa4 100644
--- a/tests/suites/test_suite_cipher.aes.data
+++ b/tests/suites/test_suite_cipher.aes.data
@@ -414,7 +414,7 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CFB
 enc_dec_buf:MBEDTLS_CIPHER_AES_128_CFB128:"AES-128-CFB128":128:32:-1
 
-AES-128 CFB - Encrypt and decrypt 32 bytes
+AES-128 CFB - Encrypt and decrypt 33 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CFB
 enc_dec_buf:MBEDTLS_CIPHER_AES_128_CFB128:"AES-128-CFB128":128:33:-1
 
@@ -474,6 +474,174 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CFB
 enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_CFB128:128:16:16:-1:16:16:16:16
 
+AES-128 OFB - Encrypt and decrypt 0 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:0:-1
+
+AES-128 OFB - Encrypt and decrypt 1 byte
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:1:-1
+
+AES-128 OFB - Encrypt and decrypt 2 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:2:-1
+
+AES-128 OFB - Encrypt and decrypt 7 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:7:-1
+
+AES-128 OFB - Encrypt and decrypt 8 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:8:-1
+
+AES-128 OFB - Encrypt and decrypt 9 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:9:-1
+
+AES-128 OFB - Encrypt and decrypt 15 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:15:-1
+
+AES-128 OFB - Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:16:-1
+
+AES-128 OFB - Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:17:-1
+
+AES-128 OFB - Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:31:-1
+
+AES-128 OFB - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:32:-1
+
+AES-128 OFB - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:33:-1
+
+AES-128 OFB - Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:47:-1
+
+AES-128 OFB - Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:48:-1
+
+AES-128 OFB - Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:49:-1
+
+AES-128 OFB - Encrypt and decrypt 0 bytes in multiple parts
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:0:0:-1:0:0:0:0
+
+AES-128 OFB - Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:1:0:-1:1:0:1:0
+
+AES-128 OFB - Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:0:1:-1:0:1:0:1
+
+AES-128 OFB - Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:16:0:-1:16:0:16:0
+
+AES-128 OFB - Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:0:16:-1:0:16:0:16
+
+AES-128 OFB - Encrypt and decrypt 16 bytes in multiple parts 3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:1:15:-1:1:15:1:15
+
+AES-128 OFB - Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:15:1:-1:15:1:15:1
+
+AES-128 OFB - Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:15:7:-1:15:7:15:7
+
+AES-128 OFB - Encrypt and decrypt 22 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:16:6:-1:16:6:16:6
+
+AES-128 OFB - Encrypt and decrypt 23 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:17:6:-1:17:6:17:6
+
+AES-128 OFB - Encrypt and decrypt 32 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:16:16:-1:16:16:16:16
+
+AES-128 XTS - Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:16:-1
+
+AES-128 XTS - Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:17:-1
+
+AES-128 XTS - Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:31:-1
+
+AES-128 XTS - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:32:-1
+
+AES-128 XTS - Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:33:-1
+
+AES-128 XTS - Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:47:-1
+
+AES-128 XTS - Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:48:-1
+
+AES-128 XTS - Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:49:-1
+
+AES-256 XTS - Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:16:-1
+
+AES-256 XTS - Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:17:-1
+
+AES-256 XTS - Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:31:-1
+
+AES-256 XTS - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:32:-1
+
+AES-256 XTS - Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:33:-1
+
+AES-256 XTS - Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:47:-1
+
+AES-256 XTS - Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:48:-1
+
+AES-256 XTS - Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:49:-1
+
 AES-128 CTR - Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 enc_dec_buf:MBEDTLS_CIPHER_AES_128_CTR:"AES-128-CTR":128:0:-1
@@ -518,7 +686,7 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 enc_dec_buf:MBEDTLS_CIPHER_AES_128_CTR:"AES-128-CTR":128:32:-1
 
-AES-128 CTR - Encrypt and decrypt 32 bytes
+AES-128 CTR - Encrypt and decrypt 33 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 enc_dec_buf:MBEDTLS_CIPHER_AES_128_CTR:"AES-128-CTR":128:33:-1
 
diff --git a/tests/suites/test_suite_cipher.chacha20.data b/tests/suites/test_suite_cipher.chacha20.data
new file mode 100644
index 0000000..c67e582
--- /dev/null
+++ b/tests/suites/test_suite_cipher.chacha20.data
@@ -0,0 +1,115 @@
+Decrypt empty buffer
+depends_on:MBEDTLS_CHACHA20_C
+dec_empty_buf:
+
+Chacha20 RFC 7539 Test Vector #1
+depends_on:MBEDTLS_CHACHA20_C
+decrypt_test_vec:MBEDTLS_CIPHER_CHACHA20:-1:"0000000000000000000000000000000000000000000000000000000000000000":"000000000000000000000000":"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"":"":0:0
+
+ChaCha20 Encrypt and decrypt 0 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:0:-1
+
+ChaCha20 Encrypt and decrypt 1 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:1:-1
+
+ChaCha20 Encrypt and decrypt 2 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:2:-1
+
+ChaCha20 Encrypt and decrypt 7 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:7:-1
+
+ChaCha20 Encrypt and decrypt 8 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:8:-1
+
+ChaCha20 Encrypt and decrypt 9 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:9:-1
+
+ChaCha20 Encrypt and decrypt 15 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:15:-1
+
+ChaCha20 Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:16:-1
+
+ChaCha20 Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:17:-1
+
+ChaCha20 Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:31:-1
+
+ChaCha20 Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:32:-1
+
+ChaCha20 Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:33:-1
+
+ChaCha20 Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:47:-1
+
+ChaCha20 Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:48:-1
+
+ChaCha20 Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:49:-1
+
+ChaCha20 Encrypt and decrypt 0 bytes in multiple parts 1
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:0:0:-1:0:0:0:0
+
+ChaCha20 Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:1:0:-1:1:0:1:0
+
+ChaCha20 Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:0:1:-1:0:1:0:1
+
+ChaCha20 Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:16:0:-1:16:0:16:0
+
+ChaCha20 Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:0:16:-1:0:16:0:16
+
+ChaCha20 Encrypt and decrypt 16 bytes in multiple parts 3
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:1:15:-1:1:15:1:15
+
+ChaCha20 Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:15:1:-1:15:1:15:1
+
+ChaCha20 Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:15:7:-1:15:7:15:7
+
+ChaCha20 Encrypt and decrypt 22 bytes in multiple parts 2
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:7:15:-1:7:15:7:15
+
+ChaCha20 Encrypt and decrypt 22 bytes in multiple parts 3
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:16:6:-1:16:6:16:6
+
+ChaCha20 Encrypt and decrypt 22 bytes in multiple parts 4
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:6:16:-1:6:16:6:16
+
+ChaCha20 Encrypt and decrypt 32 bytes in multiple parts
+depends_on:MBEDTLS_CHACHA20_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:16:16:-1:16:16:16:16
diff --git a/tests/suites/test_suite_cipher.chachapoly.data b/tests/suites/test_suite_cipher.chachapoly.data
new file mode 100644
index 0000000..1760dc0
--- /dev/null
+++ b/tests/suites/test_suite_cipher.chachapoly.data
@@ -0,0 +1,123 @@
+Decrypt empty buffer
+depends_on:MBEDTLS_CHACHAPOLY_C:
+dec_empty_buf:
+
+ChaCha20+Poly1305 Encrypt and decrypt 0 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:0:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 1 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:1:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 2 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:2:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 7 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:7:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 8 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:8:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 9 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:9:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 15 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:15:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:16:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:17:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:31:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:32:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:33:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:47:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:48:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:49:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 0 bytes in multiple parts 1
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:0:0:-1:0:0:0:0
+
+ChaCha20+Poly1305 Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:1:0:-1:1:0:1:0
+
+ChaCha20+Poly1305 Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:0:1:-1:0:1:0:1
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:16:0:-1:16:0:16:0
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:0:16:-1:0:16:0:16
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes in multiple parts 3
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:1:15:-1:1:15:1:15
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:15:1:-1:15:1:15:1
+
+ChaCha20+Poly1305 Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:15:7:-1:15:7:15:7
+
+ChaCha20+Poly1305 Encrypt and decrypt 22 bytes in multiple parts 2
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:7:15:-1:7:15:7:15
+
+ChaCha20+Poly1305 Encrypt and decrypt 22 bytes in multiple parts 3
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:16:6:-1:16:6:16:6
+
+ChaCha20+Poly1305 Encrypt and decrypt 22 bytes in multiple parts 4
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:6:16:-1:6:16:6:16
+
+ChaCha20+Poly1305 Encrypt and decrypt 32 bytes in multiple parts
+depends_on:MBEDTLS_CHACHAPOLY_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:16:16:-1:16:16:16:16
+
+ChaCha20+Poly1305 RFC 7539 Test Vector #1
+depends_on:MBEDTLS_CHACHAPOLY_C
+auth_crypt_tv:MBEDTLS_CIPHER_CHACHA20_POLY1305:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"000000000102030405060708":"f33388860000000000004e91":"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b":"eead9d67890cbb22392336fea1851f38":"496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d"
+
+ChaCha20+Poly1305 RFC 7539 Test Vector #1 Unauthentic (1st bit flipped)
+depends_on:MBEDTLS_CHACHAPOLY_C
+auth_crypt_tv:MBEDTLS_CIPHER_CHACHA20_POLY1305:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"000000000102030405060708":"f33388860000000000004e91":"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b":"6ead9d67890cbb22392336fea1851f38":"FAIL"
+
+Chacha20+Poly1305 RFC 7539 Test Vector #1 (streaming)
+depends_on:MBEDTLS_CHACHAPOLY_C
+decrypt_test_vec:MBEDTLS_CIPHER_CHACHA20_POLY1305:-1:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"000000000102030405060708":"64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b":"496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d":"f33388860000000000004e91":"eead9d67890cbb22392336fea1851f38":0:0
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index 8f1109e..b7037a0 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -60,7 +60,7 @@
     TEST_ASSERT( mbedtls_cipher_reset( NULL ) == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
     TEST_ASSERT( mbedtls_cipher_reset( &ctx ) == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( mbedtls_cipher_update_ad( NULL, buf, 0 )
                  == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
     TEST_ASSERT( mbedtls_cipher_update_ad( &ctx, buf, 0 )
@@ -77,7 +77,7 @@
     TEST_ASSERT( mbedtls_cipher_finish( &ctx, buf, &olen )
                  == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( mbedtls_cipher_write_tag( NULL, buf, olen )
                  == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
     TEST_ASSERT( mbedtls_cipher_write_tag( &ctx, buf, olen )
@@ -195,7 +195,7 @@
     TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx_dec ) );
     TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx_enc ) );
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_dec, ad, sizeof( ad ) - i ) );
     TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_enc, ad, sizeof( ad ) - i ) );
 #endif
@@ -215,7 +215,7 @@
     TEST_ASSERT( 0 == mbedtls_cipher_finish( &ctx_enc, encbuf + outlen, &outlen ) );
     total_len += outlen;
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( 0 == mbedtls_cipher_write_tag( &ctx_enc, tag, sizeof( tag ) ) );
 #endif
 
@@ -236,7 +236,7 @@
     TEST_ASSERT( 0 == mbedtls_cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) );
     total_len += outlen;
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( 0 == mbedtls_cipher_check_tag( &ctx_dec, tag, sizeof( tag ) ) );
 #endif
 
@@ -292,7 +292,7 @@
 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
     TEST_ASSERT( 0 == mbedtls_cipher_set_iv( &ctx, iv, 16 ) );
     TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx ) );
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx, NULL, 0 ) );
 #endif
 
@@ -340,7 +340,7 @@
 
     TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx_dec ) );
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_dec, NULL, 0 ) );
 #endif
 
@@ -416,7 +416,7 @@
     TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx_dec ) );
     TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx_enc ) );
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_dec, NULL, 0 ) );
     TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_enc, NULL, 0 ) );
 #endif
@@ -479,16 +479,16 @@
 {
     unsigned char key[50];
     unsigned char iv[50];
-    unsigned char cipher[200];
-    unsigned char clear[200];
+    unsigned char cipher[265]; /* max length of test data so far */
+    unsigned char clear[265];
+    unsigned char output[265];
     unsigned char ad[200];
     unsigned char tag[20];
     size_t key_len, iv_len, cipher_len, clear_len;
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     size_t ad_len, tag_len;
 #endif
     mbedtls_cipher_context_t ctx;
-    unsigned char output[200];
     size_t outlen, total_len;
 
     mbedtls_cipher_init( &ctx );
@@ -505,7 +505,7 @@
     iv_len = unhexify( iv, hex_iv );
     cipher_len = unhexify( cipher, hex_cipher );
     clear_len = unhexify( clear, hex_clear );
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     ad_len = unhexify( ad, hex_ad );
     tag_len = unhexify( tag, hex_tag );
 #else
@@ -525,7 +525,7 @@
 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
     TEST_ASSERT( 0 == mbedtls_cipher_set_iv( &ctx, iv, iv_len ) );
     TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx ) );
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx, ad, ad_len ) );
 #endif
 
@@ -536,7 +536,7 @@
     TEST_ASSERT( finish_result == mbedtls_cipher_finish( &ctx, output + outlen,
                                                  &outlen ) );
     total_len += outlen;
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
     TEST_ASSERT( tag_result == mbedtls_cipher_check_tag( &ctx, tag, tag_len ) );
 #endif
 
@@ -560,14 +560,14 @@
     int ret;
     unsigned char key[50];
     unsigned char iv[50];
-    unsigned char cipher[200];
-    unsigned char clear[200];
+    unsigned char cipher[265]; /* max size of test data so far */
+    unsigned char clear[265];
+    unsigned char output[267]; /* above + 2 (overwrite check) */
     unsigned char ad[200];
     unsigned char tag[20];
     unsigned char my_tag[20];
     size_t key_len, iv_len, cipher_len, clear_len, ad_len, tag_len;
     mbedtls_cipher_context_t ctx;
-    unsigned char output[200];
     size_t outlen;
 
     mbedtls_cipher_init( &ctx );
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_poly1305.data b/tests/suites/test_suite_poly1305.data
new file mode 100644
index 0000000..13912e9
--- /dev/null
+++ b/tests/suites/test_suite_poly1305.data
@@ -0,0 +1,42 @@
+Poly1305 RFC 7539 Example And Test Vector
+mbedtls_poly1305:"85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b":"a8061dc1305136c6c22b8baf0c0127a9":"43727970746f6772617068696320466f72756d2052657365617263682047726f7570"
+
+Poly1305 RFC 7539 Test Vector #1
+mbedtls_poly1305:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+
+Poly1305 RFC 7539 Test Vector #2
+mbedtls_poly1305:"0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e":"36e5f6b5c5e06070f0efca96227a863e":"416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f"
+
+Poly1305 RFC 7539 Test Vector #3
+mbedtls_poly1305:"36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000":"f3477e7cd95417af89a6b8794c310cf0":"416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f"
+
+Poly1305 RFC 7539 Test Vector #4
+mbedtls_poly1305:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0":"4541669a7eaaee61e708dc7cbcc5eb62":"2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e"
+
+Poly1305 RFC 7539 Test Vector #5
+mbedtls_poly1305:"0200000000000000000000000000000000000000000000000000000000000000":"03000000000000000000000000000000":"ffffffffffffffffffffffffffffffff"
+
+Poly1305 RFC 7539 Test Vector #6
+mbedtls_poly1305:"02000000000000000000000000000000ffffffffffffffffffffffffffffffff":"03000000000000000000000000000000":"02000000000000000000000000000000"
+
+Poly1305 RFC 7539 Test Vector #7
+mbedtls_poly1305:"0100000000000000000000000000000000000000000000000000000000000000":"05000000000000000000000000000000":"fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000"
+
+Poly1305 RFC 7539 Test Vector #8
+mbedtls_poly1305:"0100000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101"
+
+Poly1305 RFC 7539 Test Vector #9
+mbedtls_poly1305:"0200000000000000000000000000000000000000000000000000000000000000":"faffffffffffffffffffffffffffffff":"fdffffffffffffffffffffffffffffff"
+
+Poly1305 RFC 7539 Test Vector #10
+mbedtls_poly1305:"0100000000000000040000000000000000000000000000000000000000000000":"14000000000000005500000000000000":"e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000"
+
+Poly1305 RFC 7539 Test Vector #11
+mbedtls_poly1305:"0100000000000000040000000000000000000000000000000000000000000000":"13000000000000000000000000000000":"e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000"
+
+Poly1305 Parameter validation
+poly1305_bad_params:
+
+Poly1305 Selftest
+depends_on:MBEDTLS_SELF_TEST
+poly1305_selftest:
diff --git a/tests/suites/test_suite_poly1305.function b/tests/suites/test_suite_poly1305.function
new file mode 100644
index 0000000..62d2ad9
--- /dev/null
+++ b/tests/suites/test_suite_poly1305.function
@@ -0,0 +1,140 @@
+/* BEGIN_HEADER */
+#include "mbedtls/poly1305.h"
+#include <stddef.h>
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_POLY1305_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void mbedtls_poly1305( char *hex_key_string, char *hex_mac_string, char *hex_src_string  )
+{
+    unsigned char src_str[375]; /* max size of binary input */
+    unsigned char key[32]; /* size set by the standard */
+    unsigned char mac[16]; /* size set by the standard */
+    unsigned char mac_str[33]; /* hex expansion of the above */
+    size_t src_len;
+    mbedtls_poly1305_context ctx;
+
+    memset( src_str, 0x00, sizeof( src_str ) );
+    memset( mac_str, 0x00, sizeof( mac_str ) );
+    memset( key,     0x00, sizeof( key ) );
+    memset( mac,     0x00, sizeof( mac ) );
+
+    src_len = unhexify( src_str, hex_src_string );
+    unhexify( key, hex_key_string );
+
+    /*
+     * Test the integrated API
+     */
+    TEST_ASSERT( mbedtls_poly1305_mac( key, src_str, src_len, mac ) == 0 );
+
+    hexify( mac_str, mac, 16 );
+    TEST_ASSERT( strcmp( (char *) mac_str, hex_mac_string ) == 0 );
+
+    /*
+     * Test the streaming API
+     */
+    mbedtls_poly1305_init( &ctx );
+
+    TEST_ASSERT( mbedtls_poly1305_starts( &ctx, key ) == 0 );
+
+    TEST_ASSERT( mbedtls_poly1305_update( &ctx, src_str, src_len ) == 0 );
+
+    TEST_ASSERT( mbedtls_poly1305_finish( &ctx, mac ) == 0 );
+
+    hexify( mac_str, mac, 16 );
+    TEST_ASSERT( strcmp( (char *) mac_str, hex_mac_string ) == 0 );
+
+    /*
+     * Test the streaming API again, piecewise
+     */
+
+    /* Don't free/init the context, in order to test that starts() does the
+     * right thing. */
+    if( src_len >= 1 )
+    {
+        TEST_ASSERT( mbedtls_poly1305_starts( &ctx, key ) == 0 );
+
+        TEST_ASSERT( mbedtls_poly1305_update( &ctx, src_str, 1 ) == 0 );
+        TEST_ASSERT( mbedtls_poly1305_update( &ctx, src_str + 1, src_len - 1 ) == 0 );
+
+        TEST_ASSERT( mbedtls_poly1305_finish( &ctx, mac ) == 0 );
+
+        hexify( mac_str, mac, 16 );
+        TEST_ASSERT( strcmp( (char *) mac_str, hex_mac_string ) == 0 );
+    }
+
+    /*
+     * Again with more pieces
+     */
+    if( src_len >= 2 )
+    {
+        TEST_ASSERT( mbedtls_poly1305_starts( &ctx, key ) == 0 );
+
+        TEST_ASSERT( mbedtls_poly1305_update( &ctx, src_str, 1 ) == 0 );
+        TEST_ASSERT( mbedtls_poly1305_update( &ctx, src_str + 1, 1 ) == 0 );
+        TEST_ASSERT( mbedtls_poly1305_update( &ctx, src_str + 2, src_len - 2 ) == 0 );
+
+        TEST_ASSERT( mbedtls_poly1305_finish( &ctx, mac ) == 0 );
+
+        hexify( mac_str, mac, 16 );
+        TEST_ASSERT( strcmp( (char *) mac_str, hex_mac_string ) == 0 );
+    }
+
+    mbedtls_poly1305_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void poly1305_bad_params()
+{
+    unsigned char src[1];
+    unsigned char key[32];
+    unsigned char mac[16];
+    size_t src_len = sizeof( src );
+    mbedtls_poly1305_context ctx;
+
+    mbedtls_poly1305_init( NULL );
+    mbedtls_poly1305_free( NULL );
+
+    mbedtls_poly1305_init( &ctx );
+
+    TEST_ASSERT( mbedtls_poly1305_starts( NULL, key )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_poly1305_starts( &ctx, NULL )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_poly1305_update( NULL, src, 0 )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_poly1305_update( &ctx, NULL, src_len )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_poly1305_update( &ctx, NULL, 0 )
+                 == 0 );
+
+    TEST_ASSERT( mbedtls_poly1305_finish( NULL, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_poly1305_finish( &ctx, NULL )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_poly1305_mac( NULL, src, 0, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_poly1305_mac( key, NULL, src_len, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_poly1305_mac( key, src, 0, NULL )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_poly1305_mac( key, NULL, 0, mac )
+                 == 0 );
+
+    mbedtls_poly1305_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
+void poly1305_selftest()
+{
+    TEST_ASSERT( mbedtls_poly1305_self_test( 1 ) == 0 );
+}
+/* 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..664bcad 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -158,6 +158,8 @@
     <ClInclude Include="..\..\include\mbedtls\camellia.h" />

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

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

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

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

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

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

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

@@ -178,6 +180,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 +200,8 @@
     <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\poly1305.h" />

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

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

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

@@ -230,6 +235,8 @@
     <ClCompile Include="..\..\library\camellia.c" />

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

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

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

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

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

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

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

@@ -247,6 +254,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 +274,8 @@
     <ClCompile Include="..\..\library\pkparse.c" />

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

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

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

+    <ClCompile Include="..\..\library\poly1305.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>