Merge remote-tracking branch 'upstream-public/pr/1378' into development
diff --git a/.github/issue_template.md b/.github/issue_template.md
index 5e9d83d..7c31353 100644
--- a/.github/issue_template.md
+++ b/.github/issue_template.md
@@ -38,4 +38,4 @@
 
 ## Question
 
-**Please first check for answers in the [Mbed TLS knowledge Base](https://tls.mbed.org/kb), and preferably file an issue in the [Mbed TLS support forum](https://tls.mbed.org/discussions)**  
+**Please first check for answers in the [Mbed TLS knowledge Base](https://tls.mbed.org/kb), and preferably file an issue in the [Mbed TLS support forum](https://forums.mbed.com/c/mbed-tls)**  
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0ade1d4..4dbe76e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,9 @@
 cmake_minimum_required(VERSION 2.6)
-project("mbed TLS" C)
+if(TEST_CPP)
+    project("mbed TLS" C CXX)
+else()
+    project("mbed TLS" C)
+endif()
 
 option(USE_PKCS11_HELPER_LIBRARY "Build mbed TLS with the pkcs11-helper library." OFF)
 option(ENABLE_ZLIB_SUPPORT "Build mbed TLS with zlib library." OFF)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3c6dc74..3433ed0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,38 +26,70 @@
 1. For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it.
 1. Mbed TLS is released under the Apache license, and as such, all the added files should include the Apache license header.
 
-Backports
----------
-Mbed TLS maintains some legacy branches, which are released as LTS versions. Mbed TLS should follow backwards compatibility rules, to fit with existing users. As such, backporting to these branches should be handled according to the following rules:
-  
-1. If the contribution is a new feature or enhancement, no backporting is needed.
-1. Bug fixes should be backported to the legacy branches containing these bugs.
-1. Changes in the API do not require backporting. If a bug fix introduced a new API, such as new error codes, the bug fix should be implemented differently in the legacy branch.
+API/ABI Compatibility
+---------------------
+The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches.
 
-It would be highly appreciated if a contribution would be backported to a legacy branch in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development).
-At the moment, the legacy branches are:
-  
-1. [mbedtls-1.3](https://github.com/ARMmbed/mbedtls/tree/mbedtls-1.3)
+To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change.
+
+Where changes to an existing interface are necessary, functions in the public interface which need to be changed, are marked as 'deprecated'. This is done with the preprocessor symbols `MBEDTLS_DEPRECATED_WARNING` and `MBEDTLS_DEPRECATED_REMOVED`. Then, a new function with a new name but similar if not identical behaviour to the original function containing the necessary changes should be created alongside the existing deprecated function.
+
+When a build is made with the deprecation preprocessor symbols defined, a compiler warning will be generated to warn a user that the function will be removed at some point in the future, notifying users that they should change from the older deprecated function to the newer function at their own convenience.
+
+Therefore, no changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. As described above, if a function needs to be changed, a new function needs to be created alongside it, with a new name, and whatever change is necessary, such as a new parameter or the addition of a return value.
+
+Periodically, the library will remove deprecated functions from the library which will be a breaking change in the API, but such changes will be made only in a planned, structured way that gives sufficient notice to users of the library.
+
+Long Term Support Branches
+--------------------------
+Mbed TLS maintains several LTS (Long Term Support) branches, which are maintained continuously for a given period. The LTS branches are provided to allow users of the library to have a maintained, stable version of the library which contains only security fixes and fixes for other defects, without encountering additional features or API extensions which may introduce issues or change the code size or RAM usage, which can be significant considerations on some platforms. To allow users to take advantage of the LTS branches, these branches maintain backwards compatibility for both the public API and ABI.
+
+When backporting to these branches please observe the following rules:
+
+ 1. Any change to the library which changes the API or ABI cannot be backported.
+
+ 2. All bug fixes that correct a defect that is also present in an LTS branch must be backported to that LTS branch. If a bug fix introduces a change to the API such as a new function, the fix should be reworked to avoid the API change. API changes without very strong justification are unlikely to be accepted.
+
+ 3. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be addtional test cases or quality improvements such as changes to build or test scripts.
+
+It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development) by contributors.
+
+Currently maintained LTS branches are:
+
 1. [mbedtls-2.1](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.1)
 
+2. [mbedtls-2.7](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.7)
+
+
 Tests
 -----
-As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist.  
-Mbed TLS includes an elaborate test suite in `tests/` that initially requires Perl to generate the tests files (e.g. `test_suite_mpi.c`). These files are generated from a `function file` (e.g. `suites/test_suite_mpi.function`) and a `data file` (e.g. `suites/test_suite_mpi.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function.
+As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist.
+
+Mbed TLS includes a comprehensive set of test suites in the `tests/` directory that are dynamically generated to produce the actual test source files (e.g. `test_suite_mpi.c`). These files are generated from a `function file` (e.g. `suites/test_suite_mpi.function`) and a `data file` (e.g. `suites/test_suite_mpi.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function.
+
+[A Knowledge Base article describing how to add additional tests is available on the Mbed TLS website](https://tls.mbed.org/kb/development/test_suites).
+
+A test script `tests/scripts/basic-build-test.sh` is available to show test coverage of the library. New code contributions should provide a similar level of code coverage to that which already exists for the library.
 
 Sample applications, if needed, should be modified as well.
 
 Continuous Integration Tests
 ----------------------------
-Once a PR has been made, the Continuous Integration (CI) tests are triggered and run. You should follow the result of the CI tests, and fix failures. 
+Once a PR has been made, the Continuous Integration (CI) tests are triggered and run. You should follow the result of the CI tests, and fix failures.
+
 It is advised to enable the [githooks scripts](https://github.com/ARMmbed/mbedtls/tree/development/tests/git-scripts) prior to pushing your changes, for catching some of the issues as early as possible.
 
 Documentation
 -------------
-Mbed TLS should be well documented. If documentation is needed, speak out!
+Mbed TLS is well documented, but if you think documentation is needed, speak out!
 
 1. All interfaces should be documented through Doxygen. New APIs should introduce Doxygen documentation.
-1. Complex parts in the code should include comments.
-1. If needed, a Readme file is advised.
-1. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description.
-1. A [ChangeLog](https://github.com/ARMmbed/mbedtls/blob/development/ChangeLog) entry should be added for this contribution.
+
+2. Complex parts in the code should include comments.
+
+3. If needed, a Readme file is advised.
+
+4. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description.
+
+5. A [ChangeLog](https://github.com/ARMmbed/mbedtls/blob/development/ChangeLog) entry should be added for this contribution.
+
diff --git a/ChangeLog b/ChangeLog
index 380b289..d731673 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,10 +3,117 @@
 = mbed TLS x.x.x branch released xxxx-xx-xx
 
 Bugfix
+   * Fixes an issue with MBEDTLS_CHACHAPOLY_C which would not compile if
+     MBEDTLS_ARC4_C and MBEDTLS_CIPHER_NULL_CIPHER weren't also defined. #1890
+   * Fix a memory leak in ecp_mul_comb() if ecp_precompute_comb() fails.
+     Fix contributed by Espressif Systems.
    * Add ecc extensions only if an ecc based ciphersuite is used.
      This improves compliance to RFC 4492, and as a result, solves
      interoperability issues with BouncyCastle. Raised by milenamil in #1157.
 
+Changes
+   * Copy headers preserving timestamps when doing a "make install".
+     Contributed by xueruini.
+
+= mbed TLS 2.12.0 branch released 2018-07-25
+
+Security
+   * Fix a vulnerability in TLS ciphersuites based on CBC and using SHA-384,
+     in (D)TLS 1.0 to 1.2, that allowed an active network attacker to
+     partially recover the plaintext of messages under some conditions by
+     exploiting timing measurements. With DTLS, the attacker could perform
+     this recovery by sending many messages in the same connection. With TLS
+     or if mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only
+     worked if the same secret (for example a HTTP Cookie) has been repeatedly
+     sent over connections manipulated by the attacker. Connections using GCM
+     or CCM instead of CBC, using hash sizes other than SHA-384, or using
+     Encrypt-then-Mac (RFC 7366) were not affected. The vulnerability was
+     caused by a miscalculation (for SHA-384) in a countermeasure to the
+     original Lucky 13 attack. Found by Kenny Paterson, Eyal Ronen and Adi
+     Shamir.
+   * Fix a vulnerability in TLS ciphersuites based on CBC, in (D)TLS 1.0 to
+     1.2, that allowed a local attacker, able to execute code on the local
+     machine as well as manipulate network packets, to partially recover the
+     plaintext of messages under some conditions by using a cache attack
+     targetting an internal MD/SHA buffer. With TLS or if
+     mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only worked if
+     the same secret (for example a HTTP Cookie) has been repeatedly sent over
+     connections manipulated by the attacker. Connections using GCM or CCM
+     instead of CBC or using Encrypt-then-Mac (RFC 7366) were not affected.
+     Found by Kenny Paterson, Eyal Ronen and Adi Shamir.
+   * Add a counter-measure against a vulnerability in TLS ciphersuites based
+     on CBC, in (D)TLS 1.0 to 1.2, that allowed a local attacker, able to
+     execute code on the local machine as well as manipulate network packets,
+     to partially recover the plaintext of messages under some conditions (see
+     previous entry) by using a cache attack targeting the SSL input record
+     buffer. Connections using GCM or CCM instead of CBC or using
+     Encrypt-then-Mac (RFC 7366) were not affected. Found by Kenny Paterson,
+     Eyal Ronen and Adi Shamir.
+
+Features
+   * Add new crypto primitives from RFC 7539: stream cipher Chacha20, one-time
+     authenticator Poly1305 and AEAD construct Chacha20-Poly1305. Contributed
+     by Daniel King.
+   * Add support for CHACHA20-POLY1305 ciphersuites from RFC 7905.
+   * Add platform support for the Haiku OS. (https://www.haiku-os.org).
+     Contributed by Augustin Cavalier.
+   * Make the receive and transmit buffers independent sizes, for situations
+     where the outgoing buffer can be fixed at a smaller size than the incoming
+     buffer, which can save some RAM. If buffer lengths are kept equal, there
+     is no functional difference. Contributed by Angus Gratton, and also
+     independently contributed again by Paul Sokolovsky.
+   * Add support for key wrapping modes based on AES as defined by
+     NIST SP 800-38F algorithms KW and KWP and by RFC 3394 and RFC 5649.
+
+Bugfix
+   * Fix the key_app_writer example which was writing a leading zero byte which
+     was creating an invalid ASN.1 tag. Found by Aryeh R. Fixes #1257.
+   * Fix compilation error on C++, because of a variable named new.
+     Found and fixed by Hirotaka Niisato in #1783.
+   * Fix "no symbols" warning issued by ranlib when building on Mac OS X. Fix
+     contributed by tabascoeye.
+   * Clarify documentation for mbedtls_ssl_write() to include 0 as a valid
+     return value. Found by @davidwu2000. #839
+   * Fix a memory leak in mbedtls_x509_csr_parse(), found by catenacyber,
+     Philippe Antoine. Fixes #1623.
+   * Remove unused headers included in x509.c. Found by Chris Hanson and fixed
+     by Brendan Shanks. Part of a fix for #992.
+   * Fix compilation error when MBEDTLS_ARC4_C is disabled and
+     MBEDTLS_CIPHER_NULL_CIPHER is enabled. Found by TrinityTonic in #1719.
+   * Added length checks to some TLS parsing functions. Found and fixed by
+     Philippe Antoine from Catena cyber. #1663.
+   * Fix the inline assembly for the MPI multiply helper function for i386 and
+     i386 with SSE2. Found by László Langó. Fixes #1550
+   * Fix namespacing in header files. Remove the `mbedtls` namespacing in
+     the `#include` in the header files. Resolves #857
+   * Fix compiler warning of 'use before initialisation' in
+     mbedtls_pk_parse_key(). Found by Martin Boye Petersen and fixed by Dawid
+     Drozd. #1098
+   * Fix decryption for zero length messages (which contain all padding) when a
+     CBC based ciphersuite is used together with Encrypt-then-MAC. Previously,
+     such a message was wrongly reported as an invalid record and therefore lead
+     to the connection being terminated. Seen most often with OpenSSL using
+     TLS 1.0. Reported by @kFYatek and by Conor Murphy on the forum. Fix
+     contributed by Espressif Systems. Fixes #1632
+   * Fix ssl_client2 example to send application data with 0-length content
+     when the request_size argument is set to 0 as stated in the documentation.
+     Fixes #1833.
+   * Correct the documentation for `mbedtls_ssl_get_session()`. This API has
+     deep copy of the session, and the peer certificate is not lost. Fixes #926.
+   * Fix build using -std=c99. Fixed by Nick Wilson.
+
+Changes
+   * Fail when receiving a TLS alert message with an invalid length, or invalid
+     zero-length messages when using TLS 1.2. Contributed by Espressif Systems.
+   * Change the default behaviour of mbedtls_hkdf_extract() to return an error
+     when calling with a NULL salt and non-zero salt_len. Contributed by
+     Brian J Murray
+   * Change the shebang line in Perl scripts to look up perl in the PATH.
+     Contributed by fbrosson.
+   * Allow overriding the time on Windows via the platform-time abstraction.
+     Fixed by Nick Wilson.
+   * Use gmtime_r/gmtime_s for thread-safety. Fixed by Nick Wilson.
+
 = mbed TLS 2.11.0 branch released 2018-06-18
 
 Features
diff --git a/Makefile b/Makefile
index a0fcb2b..78c1acb 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,7 @@
 ifndef WINDOWS
 install: no_test
 	mkdir -p $(DESTDIR)/include/mbedtls
-	cp -r include/mbedtls $(DESTDIR)/include
+	cp -rp include/mbedtls $(DESTDIR)/include
 
 	mkdir -p $(DESTDIR)/lib
 	cp -RP library/libmbedtls.*    $(DESTDIR)/lib
diff --git a/README.md b/README.md
index a2c3c6f..6345848 100644
--- a/README.md
+++ b/README.md
@@ -82,7 +82,7 @@
 
 Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://tls.mbed.org/kb) for articles on your platform or issue.
 
-In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS knowledge base](https://tls.mbed.org/kb).
+In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://tls.mbed.org/kb).
 
 ### CMake
 
@@ -192,7 +192,7 @@
 Porting Mbed TLS
 ----------------
 
-Mbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following knowledge base articles useful:
+Mbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following Knowledge Base articles useful:
 
 -   [Porting Mbed TLS to a new environment or OS](https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS)
 -   [What external dependencies does Mbed TLS rely on?](https://tls.mbed.org/kb/development/what-external-dependencies-does-mbedtls-rely-on)
@@ -211,7 +211,7 @@
 
 ### Making a Contribution
 
-1.  [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://tls.mbed.org/discussions) around a feature idea or a bug.
+1.  [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://forums.mbed.com/c/mbed-tls) around a feature idea or a bug.
 2.  Fork the [Mbed TLS repository on GitHub](https://github.com/ARMmbed/mbedtls) to start making your changes. As a general rule, you should use the "development" branch as a basis.
 3.  Write a test which shows that the bug was fixed or that the feature works as expected.
 4.  Send a pull request and bug us until it gets merged and published. Contributions may need some modifications, so work with us to get your change accepted. We will include your name in the ChangeLog :)
diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h
index a783e6b..c9b58dd 100644
--- a/configs/config-ccm-psk-tls1_2.h
+++ b/configs/config-ccm-psk-tls1_2.h
@@ -81,7 +81,7 @@
  * both ends of the connection!  (See comments in "mbedtls/ssl.h".)
  * The optimal size here depends on the typical size of records.
  */
-#define MBEDTLS_SSL_MAX_CONTENT_LEN             512
+#define MBEDTLS_SSL_MAX_CONTENT_LEN             1024
 
 #include "mbedtls/check_config.h"
 
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index ed78eb4..f695dd2 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -24,7 +24,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.11.0 source code documentation
+ * @mainpage mbed TLS v2.12.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 fdeab7a..317eb0d 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.11.0"
+PROJECT_NAME           = "mbed TLS v2.12.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/bn_mul.h b/include/mbedtls/bn_mul.h
index f4b2b56..b587317 100644
--- a/include/mbedtls/bn_mul.h
+++ b/include/mbedtls/bn_mul.h
@@ -49,7 +49,14 @@
 /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
 #if defined(__GNUC__) && \
     ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
-#if defined(__i386__)
+
+/*
+ * Disable use of the i386 assembly code below if option -O0, to disable all
+ * compiler optimisations, is passed, detected with __OPTIMIZE__
+ * This is done as the number of registers used in the assembly code doesn't
+ * work with the -O0 option.
+ */
+#if defined(__i386__) && defined(__OPTIMIZE__)
 
 #define MULADDC_INIT                        \
     asm(                                    \
@@ -142,7 +149,7 @@
         "movl   %%esi, %3       \n\t"   \
         : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
         : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
-        : "eax", "ecx", "edx", "esi", "edi"             \
+        : "eax", "ebx", "ecx", "edx", "esi", "edi"      \
     );
 
 #else
@@ -154,7 +161,7 @@
         "movl   %%esi, %3       \n\t"   \
         : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
         : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
-        : "eax", "ecx", "edx", "esi", "edi"             \
+        : "eax", "ebx", "ecx", "edx", "esi", "edi"      \
     );
 #endif /* SSE2 */
 #endif /* i386 */
diff --git a/include/mbedtls/chacha20.h b/include/mbedtls/chacha20.h
new file mode 100644
index 0000000..47bd7d3
--- /dev/null
+++ b/include/mbedtls/chacha20.h
@@ -0,0 +1,212 @@
+/**
+ * \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         -0x0051 /**< Invalid input parameter(s). */
+#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE    -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */
+#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED        -0x0055  /**< Chacha20 hardware accelerator failed. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDTLS_CHACHA20_ALT)
+
+typedef struct
+{
+    uint32_t state[16];          /*! The state (before 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 multiple 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 );
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief           The ChaCha20 checkup routine.
+ *
+ * \return          \c 0 on success.
+ * \return          \c 1 on failure.
+ */
+int mbedtls_chacha20_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST */
+
+#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..42b2b23
--- /dev/null
+++ b/include/mbedtls/chachapoly.h
@@ -0,0 +1,355 @@
+/**
+ * \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
+
+/* for shared error codes */
+#include "poly1305.h"
+
+#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE            -0x0054 /**< The requested operation is not permitted in the current state. */
+#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED          -0x0056 /**< Authenticated decryption failed: data was not authentic. */
+
+#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"
+
+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 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().
+ *
+ * \warning         Decryption with the piecewise API is discouraged! Always
+ *                  use \c mbedtls_chachapoly_auth_decrypt() when possible!
+ *
+ *                  If however this is not possible because the data is too
+ *                  large to fit in memory, you need to:
+ *
+ *                  - call \c mbedtls_chachapoly_starts() and (if needed)
+ *                  \c mbedtls_chachapoly_update_aad() as above,
+ *                  - call \c mbedtls_chachapoly_update() multiple times and
+ *                  ensure its output (the plaintext) is NOT used in any other
+ *                  way than placing it in temporary storage at this point,
+ *                  - call \c mbedtls_chachapoly_finish() to compute the
+ *                  authentication tag and compared it in constant time to the
+ *                  tag received with the ciphertext.
+ *
+ *                  If the tags are not equal, you must immediately discard
+ *                  all previous outputs of \c mbedtls_chachapoly_update(),
+ *                  otherwise you can now safely use the plaintext.
+ *
+ * \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_POLY1305_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.
+ *
+ * \warning         Decryption with the piecewise API is discouraged, see the
+ *                  warning on \c mbedtls_chachapoly_init().
+ *
+ * \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 (discouraged, see warning).
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_POLY1305_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 from the 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.
+ *
+ * \warning         Decryption with the piecewise API is discouraged, see the
+ *                  warning on \c mbedtls_chachapoly_init().
+ *
+ * \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_POLY1305_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.
+ *
+ * \warning         Decryption with the piecewise API is discouraged, see the
+ *                  warning on \c mbedtls_chachapoly_init().
+ *
+ * \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_POLY1305_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.
+ *
+ * \warning         Decryption with the piecewise API is discouraged, see the
+ *                  warning on \c mbedtls_chachapoly_init().
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_POLY1305_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
+ *                  authenticated encryption 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 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_POLY1305_BAD_INPUT_DATA
+ *                  if one or more of the required parameters are NULL.
+ */
+int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
+                                        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_POLY1305_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 );
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief           The ChaCha20-Poly1305 checkup routine.
+ *
+ * \return          \c 0 on success.
+ * \return          \c 1 on failure.
+ */
+int mbedtls_chachapoly_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CHACHAPOLY_H */
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 4689f3a..9e6bb8a 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -87,6 +87,11 @@
 #error "MBEDTLS_CMAC_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_NIST_KW_C) && \
+    ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) )
+#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C)
 #error "MBEDTLS_ECDH_C defined, but not all prerequisites"
 #endif
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 0a545eb..7f3477a 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
 
@@ -45,7 +45,8 @@
 #define MBEDTLS_CIPHER_MODE_WITH_PADDING
 #endif
 
-#if defined(MBEDTLS_ARC4_C)
+#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \
+    defined(MBEDTLS_CHACHA20_C)
 #define MBEDTLS_CIPHER_MODE_STREAM
 #endif
 
@@ -87,6 +88,7 @@
     MBEDTLS_CIPHER_ID_BLOWFISH,  /**< The Blowfish cipher. */
     MBEDTLS_CIPHER_ID_ARC4,      /**< The RC4 cipher. */
     MBEDTLS_CIPHER_ID_ARIA,      /**< The Aria cipher. */
+    MBEDTLS_CIPHER_ID_CHACHA20,  /**< The ChaCha20 cipher. */
 } mbedtls_cipher_id_t;
 
 /**
@@ -169,6 +171,8 @@
     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. */
@@ -183,6 +187,7 @@
     MBEDTLS_MODE_STREAM,                 /**< The stream cipher mode. */
     MBEDTLS_MODE_CCM,                    /**< The CCM cipher mode. */
     MBEDTLS_MODE_XTS,                    /**< The XTS cipher mode. */
+    MBEDTLS_MODE_CHACHAPOLY,             /**< The ChaCha-Poly cipher mode. */
 } mbedtls_cipher_mode_t;
 
 /** Supported cipher padding types. */
@@ -586,11 +591,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.
@@ -601,7 +606,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
@@ -659,10 +664,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.
@@ -677,7 +682,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.
@@ -689,7 +694,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/cmac.h b/include/mbedtls/cmac.h
index 913c05f..a4fd552 100644
--- a/include/mbedtls/cmac.h
+++ b/include/mbedtls/cmac.h
@@ -28,7 +28,7 @@
 #ifndef MBEDTLS_CMAC_H
 #define MBEDTLS_CMAC_H
 
-#include "mbedtls/cipher.h"
+#include "cipher.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/include/mbedtls/compat-1.3.h b/include/mbedtls/compat-1.3.h
index 600a0f1..213b691 100644
--- a/include/mbedtls/compat-1.3.h
+++ b/include/mbedtls/compat-1.3.h
@@ -1378,7 +1378,8 @@
 #define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED
 #define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED
 #define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED
-#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN
+#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \
+                         ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) )
 #define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES
 #define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT
 #define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 34dbec0..70820be 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -89,6 +89,28 @@
 //#define MBEDTLS_NO_UDBL_DIVISION
 
 /**
+ * \def MBEDTLS_NO_64BIT_MULTIPLICATION
+ *
+ * The platform lacks support for 32x32 -> 64-bit multiplication.
+ *
+ * Used in:
+ *      library/poly1305.c
+ *
+ * Some parts of the library may use multiplication of two unsigned 32-bit
+ * operands with a 64-bit result in order to speed up computations. On some
+ * platforms, this is not available in hardware and has to be implemented in
+ * software, usually in a library provided by the toolchain.
+ *
+ * Sometimes it is not desirable to have to link to that library. This option
+ * removes the dependency of that library on platforms that lack a hardware
+ * 64-bit multiplier by embedding a software implementation in Mbed TLS.
+ *
+ * Note that depending on the compiler, this may decrease performance compared
+ * to using the library function provided by the toolchain.
+ */
+//#define MBEDTLS_NO_64BIT_MULTIPLICATION
+
+/**
  * \def MBEDTLS_HAVE_SSE2
  *
  * CPU supports SSE2 instruction set.
@@ -279,14 +301,18 @@
 //#define MBEDTLS_BLOWFISH_ALT
 //#define MBEDTLS_CAMELLIA_ALT
 //#define MBEDTLS_CCM_ALT
+//#define MBEDTLS_CHACHA20_ALT
+//#define MBEDTLS_CHACHAPOLY_ALT
 //#define MBEDTLS_CMAC_ALT
 //#define MBEDTLS_DES_ALT
 //#define MBEDTLS_DHM_ALT
 //#define MBEDTLS_ECJPAKE_ALT
 //#define MBEDTLS_GCM_ALT
+//#define MBEDTLS_NIST_KW_ALT
 //#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
@@ -1945,6 +1971,26 @@
 #define MBEDTLS_CERTS_C
 
 /**
+ * \def MBEDTLS_CHACHA20_C
+ *
+ * Enable the ChaCha20 stream cipher.
+ *
+ * Module:  library/chacha20.c
+ */
+#define MBEDTLS_CHACHA20_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_CIPHER_C
  *
  * Enable the generic cipher layer.
@@ -2204,6 +2250,19 @@
 #define MBEDTLS_HMAC_DRBG_C
 
 /**
+ * \def MBEDTLS_NIST_KW_C
+ *
+ * Enable the Key Wrapping mode for 128-bit block ciphers,
+ * as defined in NIST SP 800-38F. Only KW and KWP modes
+ * are supported. At the moment, only AES is approved by NIST.
+ *
+ * Module:  library/nist_kw.c
+ *
+ * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C
+ */
+//#define MBEDTLS_NIST_KW_C
+
+/**
  * \def MBEDTLS_MD_C
  *
  * Enable the generic message digest layer.
@@ -2487,6 +2546,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.
@@ -2896,7 +2965,51 @@
 //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
 
 /* SSL options */
-//#define MBEDTLS_SSL_MAX_CONTENT_LEN             16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */
+
+/** \def MBEDTLS_SSL_MAX_CONTENT_LEN
+ *
+ * Maximum fragment length in bytes.
+ *
+ * Determines the size of both the incoming and outgoing TLS I/O buffers.
+ *
+ * Uncommenting MBEDTLS_SSL_IN_CONTENT_LEN and/or MBEDTLS_SSL_OUT_CONTENT_LEN
+ * will override this length by setting maximum incoming and/or outgoing
+ * fragment length, respectively.
+ */
+//#define MBEDTLS_SSL_MAX_CONTENT_LEN             16384
+
+/** \def MBEDTLS_SSL_IN_CONTENT_LEN
+ *
+ * Maximum incoming fragment length in bytes.
+ *
+ * Uncomment to set the size of the inward TLS buffer independently of the
+ * outward buffer.
+ */
+//#define MBEDTLS_SSL_IN_CONTENT_LEN              16384
+
+/** \def MBEDTLS_SSL_OUT_CONTENT_LEN
+ *
+ * Maximum outgoing fragment length in bytes.
+ *
+ * Uncomment to set the size of the outward TLS buffer independently of the
+ * inward buffer.
+ *
+ * It is possible to save RAM by setting a smaller outward buffer, while keeping
+ * the default inward 16384 byte buffer to conform to the TLS specification.
+ *
+ * The minimum required outward buffer size is determined by the handshake
+ * protocol's usage. Handshaking will fail if the outward buffer is too small.
+ * The specific size requirement depends on the configured ciphers and any
+ * certificate data which is sent during the handshake.
+ *
+ * For absolute minimum RAM usage, it's best to enable
+ * MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This
+ * reduces both incoming and outgoing buffer sizes. However this is only
+ * guaranteed if the other end of the connection also supports the TLS
+ * max_fragment_len extension. Otherwise the connection may fail.
+ */
+//#define MBEDTLS_SSL_OUT_CONTENT_LEN             16384
+
 //#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
 //#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
 //#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
@@ -2973,7 +3086,7 @@
 /* \} name SECTION: Customisation configuration options */
 
 /* Target and application specific configurations */
-//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h"
+//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h"
 
 #if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE)
 #include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE
diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h
index dcbc047..3835d72 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -36,7 +36,7 @@
 #include "aes.h"
 
 #if defined(MBEDTLS_THREADING_C)
-#include "mbedtls/threading.h"
+#include "threading.h"
 #endif
 
 #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED        -0x0034  /**< The entropy source failed. */
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index 13397a8..6b82d4f 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -62,7 +62,7 @@
  * DES       2  0x0032-0x0032   0x0033-0x0033
  * CTR_DBRG  4  0x0034-0x003A
  * ENTROPY   3  0x003C-0x0040   0x003D-0x003F
- * NET      11  0x0042-0x0052   0x0043-0x0045
+ * NET      13  0x0042-0x0052   0x0043-0x0049
  * ARIA      4  0x0058-0x005E
  * ASN1      7  0x0060-0x006C
  * CMAC      1  0x007A-0x007A
@@ -77,6 +77,9 @@
  * SHA1      1                  0x0035-0x0035
  * SHA256    1                  0x0037-0x0037
  * SHA512    1                  0x0039-0x0039
+ * CHACHA20  3                  0x0051-0x0055
+ * POLY1305  3                  0x0057-0x005B
+ * CHACHAPOLY 2 0x0054-0x0056
  *
  * High-level module nr (3 bits - 0x0...-0x7...)
  * Name      ID  Nr of Errors
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index e0821cf..2608de8 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -27,7 +27,7 @@
 #include "md.h"
 
 #if defined(MBEDTLS_THREADING_C)
-#include "mbedtls/threading.h"
+#include "threading.h"
 #endif
 
 /*
diff --git a/include/mbedtls/net.h b/include/mbedtls/net.h
index 28ae821..6c13b53 100644
--- a/include/mbedtls/net.h
+++ b/include/mbedtls/net.h
@@ -1,7 +1,7 @@
 /**
  * \file net.h
  *
- * \brief Deprecated header file that includes mbedtls/net_sockets.h
+ * \brief Deprecated header file that includes net_sockets.h
  *
  * \deprecated Superseded by mbedtls/net_sockets.h
  */
@@ -25,7 +25,7 @@
  */
 
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
-#include "mbedtls/net_sockets.h"
+#include "net_sockets.h"
 #if defined(MBEDTLS_DEPRECATED_WARNING)
 #warning "Deprecated header file: Superseded by mbedtls/net_sockets.h"
 #endif /* MBEDTLS_DEPRECATED_WARNING */
diff --git a/include/mbedtls/net_sockets.h b/include/mbedtls/net_sockets.h
index 0f9b31e..9f07eeb 100644
--- a/include/mbedtls/net_sockets.h
+++ b/include/mbedtls/net_sockets.h
@@ -1,7 +1,23 @@
 /**
  * \file net_sockets.h
  *
- * \brief Network communication functions
+ * \brief   Network sockets abstraction layer to integrate Mbed TLS into a
+ *          BSD-style sockets API.
+ *
+ *          The network sockets module provides an example integration of the
+ *          Mbed TLS library into a BSD sockets implementation. The module is
+ *          intended to be an example of how Mbed TLS can be integrated into a
+ *          networking stack, as well as to be Mbed TLS's network integration
+ *          for its supported platforms.
+ *
+ *          The module is intended only to be used with the Mbed TLS library and
+ *          is not intended to be used by third party application software
+ *          directly.
+ *
+ *          The supported platforms are as follows:
+ *              * Microsoft Windows and Windows CE
+ *              * POSIX/Unix platforms including Linux, OS X
+ *
  */
 /*
  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
diff --git a/include/mbedtls/nist_kw.h b/include/mbedtls/nist_kw.h
new file mode 100644
index 0000000..5a0f656
--- /dev/null
+++ b/include/mbedtls/nist_kw.h
@@ -0,0 +1,178 @@
+/**
+ * \file nist_kw.h
+ *
+ * \brief This file provides an API for key wrapping (KW) and key wrapping with
+ *        padding (KWP) as defined in NIST SP 800-38F.
+ *        https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
+ *
+ *        Key wrapping specifies a deterministic authenticated-encryption mode
+ *        of operation, according to <em>NIST SP 800-38F: Recommendation for
+ *        Block Cipher Modes of Operation: Methods for Key Wrapping</em>. Its
+ *        purpose is to protect cryptographic keys.
+ *
+ *        Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP.
+ *        https://tools.ietf.org/html/rfc3394
+ *        https://tools.ietf.org/html/rfc5649
+ *
+ */
+/*
+ *  Copyright (C) 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_NIST_KW_H
+#define MBEDTLS_NIST_KW_H
+
+#include "cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+    MBEDTLS_KW_MODE_KW = 0,
+    MBEDTLS_KW_MODE_KWP = 1
+} mbedtls_nist_kw_mode_t;
+
+#if !defined(MBEDTLS_NIST_KW_ALT)
+// Regular implementation
+//
+
+/**
+ * \brief    The key wrapping context-type definition. The key wrapping context is passed
+ *           to the APIs called.
+ *
+ * \note     The definition of this type may change in future library versions.
+ *           Don't make any assumptions on this context!
+ */
+typedef struct {
+    mbedtls_cipher_context_t cipher_ctx;    /*!< The cipher context used. */
+} mbedtls_nist_kw_context;
+
+#else  /* MBEDTLS_NIST_key wrapping_ALT */
+#include "nist_kw_alt.h"
+#endif /* MBEDTLS_NIST_KW_ALT */
+
+/**
+ * \brief           This function initializes the specified key wrapping context
+ *                  to make references valid and prepare the context
+ *                  for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free().
+ *
+ * \param ctx       The key wrapping context to initialize.
+ *
+ */
+void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx );
+
+/**
+ * \brief           This function initializes the key wrapping context set in the
+ *                  \p ctx parameter and sets the encryption key.
+ *
+ * \param ctx       The key wrapping context.
+ * \param cipher    The 128-bit block cipher to use. Only AES is supported.
+ * \param key       The Key Encryption Key (KEK).
+ * \param keybits   The KEK size in bits. This must be acceptable by the cipher.
+ * \param is_wrap   Specify whether the operation within the context is wrapping or unwrapping
+ *
+ * \return          \c 0 on success.
+ * \return          \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input.
+ * \return          \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers
+ *                  which are not supported.
+ * \return          cipher-specific error code on failure of the underlying cipher.
+ */
+int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
+                            mbedtls_cipher_id_t cipher,
+                            const unsigned char *key,
+                            unsigned int keybits,
+                            const int is_wrap );
+
+/**
+ * \brief   This function releases and clears the specified key wrapping context
+ *          and underlying cipher sub-context.
+ *
+ * \param ctx       The key wrapping context to clear.
+ */
+void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx );
+
+/**
+ * \brief           This function encrypts a buffer using key wrapping.
+ *
+ * \param ctx       The key wrapping context to use for encryption.
+ * \param mode      The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)
+ * \param input     The buffer holding the input data.
+ * \param in_len    The length of the input data in Bytes.
+ *                  The input uses units of 8 Bytes called semiblocks.
+ *                  <ul><li>For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive. </li>
+ *                  <li>For KWP mode: any length between 1 and 2^32-1 inclusive.</li></ul>
+ * \param[out] output    The buffer holding the output data.
+ *                  <ul><li>For KW mode: Must be at least 8 bytes larger than \p in_len.</li>
+ *                  <li>For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of
+ *                  8 bytes for KWP (15 bytes at most).</li></ul>
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure.
+ * \param[in] out_size The capacity of the output buffer.
+ *
+ * \return          \c 0 on success.
+ * \return          \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
+ * \return          cipher-specific error code on failure of the underlying cipher.
+ */
+int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,
+                          const unsigned char *input, size_t in_len,
+                          unsigned char *output, size_t* out_len, size_t out_size );
+
+/**
+ * \brief           This function decrypts a buffer using key wrapping.
+ *
+ * \param ctx       The key wrapping context to use for decryption.
+ * \param mode      The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)
+ * \param input     The buffer holding the input data.
+ * \param in_len    The length of the input data in Bytes.
+ *                  The input uses units of 8 Bytes called semiblocks.
+ *                  The input must be a multiple of semiblocks.
+ *                  <ul><li>For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive. </li>
+ *                  <li>For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.</li></ul>
+ * \param[out] output    The buffer holding the output data.
+ *                  The output buffer's minimal length is 8 bytes shorter than \p in_len.
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure.
+ *                  For KWP mode, the length could be up to 15 bytes shorter than \p in_len,
+ *                  depending on how much padding was added to the data.
+ * \param[in] out_size The capacity of the output buffer.
+ *
+ * \return          \c 0 on success.
+ * \return          \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
+ * \return          \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext.
+ * \return          cipher-specific error code on failure of the underlying cipher.
+ */
+int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,
+                            const unsigned char *input, size_t in_len,
+                            unsigned char *output, size_t* out_len, size_t out_size);
+
+
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+/**
+ * \brief          The key wrapping checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedtls_nist_kw_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_NIST_KW_H */
diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index 408645e..f825548 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -97,6 +97,8 @@
 /* ISO arc for standard certificate and CRL extensions */
 #define MBEDTLS_OID_ID_CE                       MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER  ::=  {joint-iso-ccitt(2) ds(5) 29} */
 
+#define MBEDTLS_OID_NIST_ALG                    MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */
+
 /**
  * Private Internet Extensions
  * { iso(1) identified-organization(3) dod(6) internet(1)
@@ -219,12 +221,12 @@
 #define MBEDTLS_OID_DIGEST_ALG_MD4              MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */
 #define MBEDTLS_OID_DIGEST_ALG_MD5              MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */
 #define MBEDTLS_OID_DIGEST_ALG_SHA1             MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */
-#define MBEDTLS_OID_DIGEST_ALG_SHA224           MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */
-#define MBEDTLS_OID_DIGEST_ALG_SHA256           MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
+#define MBEDTLS_OID_DIGEST_ALG_SHA224           MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */
+#define MBEDTLS_OID_DIGEST_ALG_SHA256           MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
 
-#define MBEDTLS_OID_DIGEST_ALG_SHA384           MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */
+#define MBEDTLS_OID_DIGEST_ALG_SHA384           MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */
 
-#define MBEDTLS_OID_DIGEST_ALG_SHA512           MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
+#define MBEDTLS_OID_DIGEST_ALG_SHA512           MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
 
 #define MBEDTLS_OID_HMAC_SHA1                   MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
 
@@ -241,8 +243,21 @@
  */
 #define MBEDTLS_OID_DES_CBC                     MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */
 #define MBEDTLS_OID_DES_EDE3_CBC                MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */
+#define MBEDTLS_OID_AES                         MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */
 
 /*
+ * Key Wrapping algorithms
+ */
+/*
+ * RFC 5649
+ */
+#define MBEDTLS_OID_AES128_KW                   MBEDTLS_OID_AES "\x05" /** id-aes128-wrap     OBJECT IDENTIFIER ::= { aes 5 } */
+#define MBEDTLS_OID_AES128_KWP                  MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */
+#define MBEDTLS_OID_AES192_KW                   MBEDTLS_OID_AES "\x19" /** id-aes192-wrap     OBJECT IDENTIFIER ::= { aes 25 } */
+#define MBEDTLS_OID_AES192_KWP                  MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */
+#define MBEDTLS_OID_AES256_KW                   MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap     OBJECT IDENTIFIER ::= { aes 45 } */
+#define MBEDTLS_OID_AES256_KWP                  MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */
+/*
  * PKCS#5 OIDs
  */
 #define MBEDTLS_OID_PKCS5_PBKDF2                MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index 9d9c529..624cc64 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -40,7 +40,7 @@
 #endif
 
 #if defined(MBEDTLS_HAVE_TIME)
-#include "mbedtls/platform_time.h"
+#include "platform_time.h"
 #endif
 
 #ifdef __cplusplus
diff --git a/include/mbedtls/poly1305.h b/include/mbedtls/poly1305.h
new file mode 100644
index 0000000..54b50ab
--- /dev/null
+++ b/include/mbedtls/poly1305.h
@@ -0,0 +1,181 @@
+/**
+ * \file poly1305.h
+ *
+ * \brief   This file contains 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. */
+#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED        -0x005B  /**< Poly1305 hardware accelerator failed. */
+
+#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 buffer into an ongoing
+ *                  Poly1305 computation.
+ *
+ *                  It is called between \c mbedtls_cipher_poly1305_starts() and
+ *                  \c mbedtls_cipher_poly1305_finish().
+ *                  It 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] );
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief           The Poly1305 checkup routine.
+ *
+ * \return          \c 0 on success.
+ * \return          \c 1 on failure.
+ */
+int mbedtls_poly1305_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_POLY1305_H */
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 4513550..2d511a8 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -62,7 +62,7 @@
 #endif
 
 #if defined(MBEDTLS_HAVE_TIME)
-#include "mbedtls/platform_time.h"
+#include "platform_time.h"
 #endif
 
 /*
@@ -220,7 +220,7 @@
 #endif
 
 /*
- * Maxium fragment length in bytes,
+ * Maximum fragment length in bytes,
  * determines the size of each of the two internal I/O buffers.
  *
  * Note: the RFC defines the default size of SSL / TLS messages. If you
@@ -234,6 +234,14 @@
 #define MBEDTLS_SSL_MAX_CONTENT_LEN         16384   /**< Size of the input / output buffer */
 #endif
 
+#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN)
+#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
+#endif
+
+#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN)
+#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
+#endif
+
 /* \} name SECTION: Module settings */
 
 /*
@@ -2418,7 +2426,8 @@
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 /**
  * \brief          Set the maximum fragment length to emit and/or negotiate
- *                 (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes)
+ *                 (Default: the smaller of MBEDTLS_SSL_IN_CONTENT_LEN and
+ *                 MBEDTLS_SSL_OUT_CONTENT_LEN, usually 2^14 bytes)
  *                 (Server: set maximum fragment length to emit,
  *                 usually negotiated by the client during handshake
  *                 (Client: set maximum fragment length to emit *and*
@@ -2737,7 +2746,6 @@
  * \brief          Save session in order to resume it later (client-side only)
  *                 Session data is copied to presented session structure.
  *
- * \warning        Currently, peer certificate is lost in the operation.
  *
  * \param ssl      SSL context
  * \param session  session context
@@ -2745,7 +2753,18 @@
  * \return         0 if successful,
  *                 MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed,
  *                 MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or
- *                 arguments are otherwise invalid
+ *                 arguments are otherwise invalid.
+ *
+ * \note           Only the server certificate is copied, and not the full chain,
+ *                 so you should not attempt to validate the certificate again
+ *                 by calling \c mbedtls_x509_crt_verify() on it.
+ *                 Instead, you should use the results from the verification
+ *                 in the original handshake by calling \c mbedtls_ssl_get_verify_result()
+ *                 after loading the session again into a new SSL context
+ *                 using \c mbedtls_ssl_set_session().
+ *
+ * \note           Once the session object is not needed anymore, you should
+ *                 free it by calling \c mbedtls_ssl_session_free().
  *
  * \sa             mbedtls_ssl_set_session()
  */
@@ -2907,17 +2926,19 @@
  *                 or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ,
  *                 or another negative error code.
  *
- * \note           If this function returns something other than a positive value
- *                 or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
- *                 the SSL context for reading or writing, and either free it or
- *                 call \c mbedtls_ssl_session_reset() on it before re-using it
- *                 for a new connection; the current connection must be closed.
+ * \note           If this function returns something other than 0, a positive
+ *                 value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop
+ *                 using the SSL context for reading or writing, and either
+ *                 free it or call \c mbedtls_ssl_session_reset() on it before
+ *                 re-using it for a new connection; the current connection
+ *                 must be closed.
  *
  * \note           When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ,
  *                 it must be called later with the *same* arguments,
- *                 until it returns a positive value. When the function returns
- *                 MBEDTLS_ERR_SSL_WANT_WRITE there may be some partial
- *                 data in the output buffer, however this is not yet sent.
+ *                 until it returns a value greater that or equal to 0. When
+ *                 the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be
+ *                 some partial data in the output buffer, however this is not
+ *                 yet sent.
  *
  * \note           If the requested length is greater than the maximum
  *                 fragment length (either the built-in limit or the one set
@@ -2926,6 +2947,9 @@
  *                 - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned.
  *                 \c mbedtls_ssl_get_max_frag_len() may be used to query the
  *                 active maximum fragment length.
+ *
+ * \note           Attempting to write 0 bytes will result in an empty TLS
+ *                 application record being sent.
  */
 int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len );
 
@@ -3018,6 +3042,9 @@
  * \brief          Free referenced items in an SSL session including the
  *                 peer certificate and clear memory
  *
+ * \note           A session object can be freed even if the SSL context
+ *                 that was used to retrieve the session is still in use.
+ *
  * \param session  SSL session
  */
 void mbedtls_ssl_session_free( mbedtls_ssl_session *session );
diff --git a/include/mbedtls/ssl_ciphersuites.h b/include/mbedtls/ssl_ciphersuites.h
index 7d5eba0..cda8b48 100644
--- a/include/mbedtls/ssl_ciphersuites.h
+++ b/include/mbedtls/ssl_ciphersuites.h
@@ -271,6 +271,15 @@
 
 #define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8          0xC0FF  /**< experimental */
 
+/* RFC 7905 */
+#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   0xCCA8 /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     0xCCAA /**< TLS 1.2 */
+#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256         0xCCAB /**< TLS 1.2 */
+#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256   0xCCAC /**< TLS 1.2 */
+#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256     0xCCAD /**< TLS 1.2 */
+#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256     0xCCAE /**< TLS 1.2 */
+
 /* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange.
  * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below
  */
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index f48fe90..d214703 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -143,32 +143,73 @@
 #define MBEDTLS_SSL_PADDING_ADD              0
 #endif
 
-#define MBEDTLS_SSL_PAYLOAD_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN    \
-                        + MBEDTLS_SSL_COMPRESSION_ADD            \
-                        + MBEDTLS_MAX_IV_LENGTH                  \
-                        + MBEDTLS_SSL_MAC_ADD                    \
-                        + MBEDTLS_SSL_PADDING_ADD                \
-                        )
+#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD +    \
+                                       MBEDTLS_MAX_IV_LENGTH +          \
+                                       MBEDTLS_SSL_MAC_ADD +            \
+                                       MBEDTLS_SSL_PADDING_ADD          \
+                                       )
+
+#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
+                                     ( MBEDTLS_SSL_IN_CONTENT_LEN ) )
+
+#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
+                                      ( MBEDTLS_SSL_OUT_CONTENT_LEN ) )
+
+/* Maximum length we can advertise as our max content length for
+   RFC 6066 max_fragment_length extension negotiation purposes
+   (the lesser of both sizes, if they are unequal.)
+ */
+#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN (                            \
+        (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN)   \
+        ? ( MBEDTLS_SSL_OUT_CONTENT_LEN )                            \
+        : ( MBEDTLS_SSL_IN_CONTENT_LEN )                             \
+        )
 
 /*
  * Check that we obey the standard's message size bounds
  */
 
 #if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384
-#error Bad configuration - record content too large.
+#error "Bad configuration - record content too large."
 #endif
 
-#if MBEDTLS_SSL_PAYLOAD_LEN > 16384 + 2048
-#error Bad configuration - protected record payload too large.
+#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN
+#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN."
 #endif
 
+#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN
+#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN."
+#endif
+
+#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048
+#error "Bad configuration - incoming protected record payload too large."
+#endif
+
+#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048
+#error "Bad configuration - outgoing protected record payload too large."
+#endif
+
+/* Calculate buffer sizes */
+
 /* Note: Even though the TLS record header is only 5 bytes
    long, we're internally using 8 bytes to store the
    implicit sequence number. */
 #define MBEDTLS_SSL_HEADER_LEN 13
 
-#define MBEDTLS_SSL_BUFFER_LEN  \
-    ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_PAYLOAD_LEN ) )
+#define MBEDTLS_SSL_IN_BUFFER_LEN  \
+    ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) )
+
+#define MBEDTLS_SSL_OUT_BUFFER_LEN  \
+    ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) )
+
+#ifdef MBEDTLS_ZLIB_SUPPORT
+/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */
+#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN (                               \
+        ( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN )      \
+        ? MBEDTLS_SSL_IN_BUFFER_LEN                                     \
+        : MBEDTLS_SSL_OUT_BUFFER_LEN                                    \
+        )
+#endif
 
 /*
  * TLS extension flags (for extensions with outgoing ServerHello content
diff --git a/include/mbedtls/threading.h b/include/mbedtls/threading.h
index aeea5d0..c25daa5 100644
--- a/include/mbedtls/threading.h
+++ b/include/mbedtls/threading.h
@@ -99,9 +99,6 @@
 #if defined(MBEDTLS_FS_IO)
 extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex;
 #endif
-#if defined(MBEDTLS_HAVE_TIME_DATE)
-extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex;
-#endif
 #endif /* MBEDTLS_THREADING_C */
 
 #ifdef __cplusplus
diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h
index c8050b9..eaf25d9 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  11
+#define MBEDTLS_VERSION_MINOR  12
 #define MBEDTLS_VERSION_PATCH  0
 
 /**
@@ -47,9 +47,9 @@
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x020B0000
-#define MBEDTLS_VERSION_STRING         "2.11.0"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.11.0"
+#define MBEDTLS_VERSION_NUMBER         0x020C0000
+#define MBEDTLS_VERSION_STRING         "2.12.0"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.12.0"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 5243baf..5115b96 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -14,6 +14,8 @@
     blowfish.c
     camellia.c
     ccm.c
+    chacha20.c
+    chachapoly.c
     cipher.c
     cipher_wrap.c
     cmac.c
@@ -38,6 +40,7 @@
     md5.c
     md_wrap.c
     memory_buffer_alloc.c
+    nist_kw.c
     oid.c
     padlock.c
     pem.c
@@ -49,6 +52,7 @@
     pkwrite.c
     platform.c
     platform_util.c
+    poly1305.c
     ripemd160.c
     rsa.c
     rsa_internal.c
@@ -98,6 +102,17 @@
     set(libs ${libs} ws2_32)
 endif(WIN32)
 
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+    SET(CMAKE_C_ARCHIVE_CREATE   "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
+    SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
+    SET(CMAKE_C_ARCHIVE_FINISH   "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
+    SET(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
+endif()
+
+if(HAIKU)
+    set(libs ${libs} network)
+endif(HAIKU)
+
 if(USE_PKCS11_HELPER_LIBRARY)
     set(libs ${libs} pkcs11-helper)
 endif(USE_PKCS11_HELPER_LIBRARY)
@@ -144,15 +159,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.11.0 SOVERSION 3)
+    set_target_properties(mbedcrypto PROPERTIES VERSION 2.12.0 SOVERSION 3)
     target_link_libraries(mbedcrypto ${libs})
 
     add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.11.0 SOVERSION 0)
+    set_target_properties(mbedx509 PROPERTIES VERSION 2.12.0 SOVERSION 0)
     target_link_libraries(mbedx509 ${libs} mbedcrypto)
 
     add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.11.0 SOVERSION 11)
+    set_target_properties(mbedtls PROPERTIES VERSION 2.12.0 SOVERSION 11)
     target_link_libraries(mbedtls ${libs} mbedx509)
 
     install(TARGETS mbedtls mbedx509 mbedcrypto
diff --git a/library/Makefile b/library/Makefile
index f7eb896..ac88d4c 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -21,6 +21,10 @@
 # if were running on Windows build for Windows
 ifdef WINDOWS
 WINDOWS_BUILD=1
+else ifeq ($(shell uname -s),Darwin)
+ifeq ($(AR),ar)
+APPLE_BUILD ?= 1
+endif
 endif
 
 # To compile as a shared library:
@@ -35,23 +39,35 @@
 SOEXT_X509=so.0
 SOEXT_CRYPTO=so.3
 
-# Set DLEXT=dylib to compile as a shared library for Mac OS X
-DLEXT ?= so
-
 # Set AR_DASH= (empty string) to use an ar implentation that does not accept
 # the - prefix for command line options (e.g. llvm-ar)
 AR_DASH ?= -
 
-# Windows shared library extension:
+ARFLAGS = $(AR_DASH)src
+ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
+ARFLAGS = $(AR_DASH)Src
+RLFLAGS = -no_warning_for_no_symbols -c
+RL ?= ranlib
+endif
+endif
+
+DLEXT ?= so
 ifdef WINDOWS_BUILD
-DLEXT=dll
+# Windows shared library extension:
+DLEXT = dll
+else ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
+# Mac OS X shared library extension:
+DLEXT = dylib
+endif
 endif
 
 OBJS_CRYPTO=	aes.o		aesni.o		arc4.o		\
-		asn1parse.o	asn1write.o	base64.o	\
-		bignum.o	blowfish.o	camellia.o	\
-		aria.o						\
-		ccm.o		cipher.o	cipher_wrap.o	\
+		aria.o		asn1parse.o	asn1write.o	\
+		base64.o	bignum.o	blowfish.o	\
+		camellia.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				\
@@ -60,15 +76,15 @@
 		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	ripemd160.o	rsa_internal.o	\
-		rsa.o 		sha1.o		sha256.o	\
-		sha512.o	threading.o	timing.o	\
-		version.o	version_features.o		\
-		xtea.o
+		memory_buffer_alloc.o		nist_kw.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	\
+		version_features.o		xtea.o
 
 OBJS_X509=	certs.o		pkcs11.o	x509.o		\
 		x509_create.o	x509_crl.o	x509_crt.o	\
@@ -97,9 +113,13 @@
 # tls
 libmbedtls.a: $(OBJS_TLS)
 	echo "  AR    $@"
-	$(AR) $(AR_DASH)rc $@ $(OBJS_TLS)
+	$(AR) $(ARFLAGS) $@ $(OBJS_TLS)
+ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
 	echo "  RL    $@"
-	$(AR) $(AR_DASH)s $@
+	$(RL) $(RLFLAGS) $@
+endif
+endif
 
 libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so
 	echo "  LD    $@"
@@ -120,9 +140,13 @@
 # x509
 libmbedx509.a: $(OBJS_X509)
 	echo "  AR    $@"
-	$(AR) $(AR_DASH)rc $@ $(OBJS_X509)
+	$(AR) $(ARFLAGS) $@ $(OBJS_X509)
+ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
 	echo "  RL    $@"
-	$(AR) $(AR_DASH)s $@
+	$(RL) $(RLFLAGS) $@
+endif
+endif
 
 libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so
 	echo "  LD    $@"
@@ -143,9 +167,13 @@
 # crypto
 libmbedcrypto.a: $(OBJS_CRYPTO)
 	echo "  AR    $@"
-	$(AR) $(AR_DASH)rc $@ $(OBJS_CRYPTO)
+	$(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO)
+ifdef APPLE_BUILD
+ifneq ($(APPLE_BUILD),0)
 	echo "  RL    $@"
-	$(AR) $(AR_DASH)s $@
+	$(RL) $(RLFLAGS) $@
+endif
+endif
 
 libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO)
 	echo "  LD    $@"
diff --git a/library/chacha20.c b/library/chacha20.c
new file mode 100644
index 0000000..d14a51e
--- /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)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CHACHA20_C)
+
+#include "mbedtls/chacha20.h"
+#include "mbedtls/platform_util.h"
+
+#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 */
+
+#if !defined(MBEDTLS_CHACHA20_ALT)
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#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 )
+
+/**
+ * \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 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 chacha20_inner_block( uint32_t state[16] )
+{
+    chacha20_quarter_round( state, 0, 4, 8,  12 );
+    chacha20_quarter_round( state, 1, 5, 9,  13 );
+    chacha20_quarter_round( state, 2, 6, 10, 14 );
+    chacha20_quarter_round( state, 3, 7, 11, 15 );
+
+    chacha20_quarter_round( state, 0, 5, 10, 15 );
+    chacha20_quarter_round( state, 1, 6, 11, 12 );
+    chacha20_quarter_round( state, 2, 7, 8,  13 );
+    chacha20_quarter_round( state, 3, 4, 9,  14 );
+}
+
+/**
+ * \brief               Generates a keystream block.
+ *
+ * \param initial_state The initial ChaCha20 state (key, nonce, counter).
+ * \param keystream     Generated keystream bytes are written to this buffer.
+ */
+static void chacha20_block( const uint32_t initial_state[16],
+                            unsigned char keystream[64] )
+{
+    uint32_t working_state[16];
+    size_t i;
+
+    memcpy( working_state,
+            initial_state,
+            CHACHA20_BLOCK_SIZE_BYTES );
+
+    for( i = 0U; i < 10U; i++ )
+        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++ )
+    {
+        size_t 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 );
+    }
+
+    mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
+}
+
+void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
+{
+    if( ctx != NULL )
+    {
+        mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
+        mbedtls_platform_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_platform_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->state[0] = 0x61707865;
+    ctx->state[1] = 0x3320646e;
+    ctx->state[2] = 0x79622d32;
+    ctx->state[3] = 0x6b206574;
+
+    /* Set key */
+    ctx->state[4]  = BYTES_TO_U32_LE( key, 0 );
+    ctx->state[5]  = BYTES_TO_U32_LE( key, 4 );
+    ctx->state[6]  = BYTES_TO_U32_LE( key, 8 );
+    ctx->state[7]  = BYTES_TO_U32_LE( key, 12 );
+    ctx->state[8]  = BYTES_TO_U32_LE( key, 16 );
+    ctx->state[9]  = BYTES_TO_U32_LE( key, 20 );
+    ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
+    ctx->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->state[12] = counter;
+
+    /* Nonce */
+    ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
+    ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
+    ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
+
+    mbedtls_platform_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 */
+        chacha20_block( ctx->state, ctx->keystream8 );
+        ctx->state[CHACHA20_CTR_INDEX]++;
+
+        for( i = 0U; i < 64U; i += 8U )
+        {
+            output[offset + i  ] = input[offset + i  ] ^ ctx->keystream8[i  ];
+            output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
+            output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
+            output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
+            output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
+            output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
+            output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
+            output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
+        }
+
+        offset += CHACHA20_BLOCK_SIZE_BYTES;
+        size   -= CHACHA20_BLOCK_SIZE_BYTES;
+    }
+
+    /* Last (partial) block */
+    if( size > 0U )
+    {
+        /* Generate new keystream block and increment counter */
+        chacha20_block( ctx->state, ctx->keystream8 );
+        ctx->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 ret;
+
+    mbedtls_chacha20_init( &ctx );
+
+    ret = mbedtls_chacha20_setkey( &ctx, key );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
+
+cleanup:
+    mbedtls_chacha20_free( &ctx );
+    return( ret );
+}
+
+#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 ret;
+
+    for( i = 0U; i < 2U; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  ChaCha20 test %u ", i );
+
+        ret = mbedtls_chacha20_crypt( test_keys[i],
+                                      test_nonces[i],
+                                      test_counters[i],
+                                      test_lengths[i],
+                                      test_input[i],
+                                      output );
+
+        ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
+
+        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..860f877
--- /dev/null
+++ b/library/chachapoly.c
@@ -0,0 +1,547 @@
+/**
+ * \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 "mbedtls/platform_util.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 )
+
+/**
+ * \brief           Adds nul bytes to pad the AAD for Poly1305.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context.
+ */
+static int 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 )
+        return( 0 );
+
+    memset( zeroes, 0, sizeof( zeroes ) );
+
+    return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
+                                     zeroes,
+                                     16U - partial_block_len ) );
+}
+
+/**
+ * \brief           Adds nul bytes to pad the ciphertext for Poly1305.
+ *
+ * \param ctx       The ChaCha20-Poly1305 context.
+ */
+static int 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 )
+        return( 0 );
+
+    memset( zeroes, 0, sizeof( zeroes ) );
+    return( 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 ret;
+
+    if( ( ctx == NULL ) || ( key == NULL ) )
+    {
+        return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    }
+
+    ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
+
+    return( ret );
+}
+
+int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
+                               const unsigned char nonce[12],
+                               mbedtls_chachapoly_mode_t mode  )
+{
+    int ret;
+    unsigned char poly1305_key[64];
+
+    if( ( ctx == NULL ) || ( nonce == NULL ) )
+    {
+        return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    }
+
+    /* Set counter = 0, will be update to 1 when generating Poly1305 key */
+    ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
+    if( ret != 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 ) );
+    ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
+                                      poly1305_key, poly1305_key );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
+
+    if( ret == 0 )
+    {
+        ctx->aad_len        = 0U;
+        ctx->ciphertext_len = 0U;
+        ctx->state          = CHACHAPOLY_STATE_AAD;
+        ctx->mode           = mode;
+    }
+
+cleanup:
+    mbedtls_platform_zeroize( poly1305_key, 64U );
+    return( ret );
+}
+
+int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
+                                   const unsigned char *aad,
+                                   size_t aad_len )
+{
+    if( ctx == NULL )
+    {
+        return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    }
+    else if( ( aad_len > 0U ) && ( aad == NULL ) )
+    {
+        /* aad pointer is allowed to be NULL if aad_len == 0 */
+        return( MBEDTLS_ERR_POLY1305_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 )
+{
+    int ret;
+
+    if( ctx == NULL )
+    {
+        return( MBEDTLS_ERR_POLY1305_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_POLY1305_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;
+
+        ret = chachapoly_pad_aad( ctx );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    ctx->ciphertext_len += len;
+
+    if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
+    {
+        ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
+        if( ret != 0 )
+            return( ret );
+
+        ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
+        if( ret != 0 )
+            return( ret );
+    }
+    else /* DECRYPT */
+    {
+        ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
+        if( ret != 0 )
+            return( ret );
+
+        ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    return( 0 );
+}
+
+int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
+                               unsigned char mac[16] )
+{
+    int ret;
+    unsigned char len_block[16];
+
+    if( ( ctx == NULL ) || ( mac == NULL ) )
+    {
+        return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    }
+    else if( ctx->state == CHACHAPOLY_STATE_INIT )
+    {
+        return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    }
+
+    if( ctx->state == CHACHAPOLY_STATE_AAD )
+    {
+        ret = chachapoly_pad_aad( ctx );
+        if( ret != 0 )
+            return( ret );
+    }
+    else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
+    {
+        ret = chachapoly_pad_ciphertext( ctx );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    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 );
+
+    ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
+    if( ret != 0 )
+        return( ret );
+
+    ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
+
+    return( ret );
+}
+
+static int 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 ret;
+
+    ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = mbedtls_chachapoly_update( ctx, length, input, output );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = mbedtls_chachapoly_finish( ctx, tag );
+
+cleanup:
+    return( ret );
+}
+
+int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
+                                        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] )
+{
+    return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                      length, nonce, aad, aad_len,
+                                      input, output, tag ) );
+}
+
+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_POLY1305_BAD_INPUT_DATA );
+
+    if( ( ret = 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_platform_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 ret;
+    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 );
+
+        ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
+        ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
+
+        ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
+                                                  test_input_len[i],
+                                                  test_nonce[i],
+                                                  test_aad[i],
+                                                  test_aad_len[i],
+                                                  test_input[i],
+                                                  output,
+                                                  mac );
+
+        ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
+
+        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 2d85228..7ae6c4a 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -38,6 +38,10 @@
 #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
@@ -46,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
@@ -57,9 +65,25 @@
 #define mbedtls_free   free
 #endif
 
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#define MBEDTLS_CIPHER_MODE_STREAM
-#endif
+#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;
 
@@ -232,6 +256,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;
 
@@ -248,22 +284,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 )
@@ -304,6 +363,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;
@@ -685,6 +753,12 @@
         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 )
@@ -796,7 +870,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 )
 {
@@ -806,8 +880,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 );
 }
@@ -815,6 +903,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 ||
@@ -823,12 +912,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 );
 
@@ -839,18 +925,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
@@ -909,6 +1015,21 @@
                                      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_encrypt_and_tag( ctx->cipher_ctx,
+                                ilen, iv, ad, ad_len, input, output, tag ) );
+    }
+#endif /* MBEDTLS_CHACHAPOLY_C */
 
     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
 }
@@ -955,6 +1076,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 16e0a9d..893490a 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
@@ -57,6 +61,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
@@ -1886,6 +1894,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_CHACHAPOLY,
+    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,
@@ -2087,6 +2251,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 4d7a1f1..5d101e1 100644
--- a/library/cmac.c
+++ b/library/cmac.c
@@ -828,6 +828,7 @@
         mbedtls_cipher_free( &ctx );
     }
 
+    ret = 0;
     goto exit;
 
 cleanup:
@@ -883,6 +884,7 @@
         if( verbose != 0 )
             mbedtls_printf( "passed\n" );
     }
+    ret = 0;
 
 exit:
     return( ret );
diff --git a/library/ecp.c b/library/ecp.c
index 41db3fb..68c6f49 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -1446,7 +1446,12 @@
 
 cleanup:
 
-    if( T != NULL && ! p_eq_g )
+    /* There are two cases where T is not stored in grp:
+     * - P != G
+     * - An intermediate operation failed before setting grp->T
+     * In either case, T must be freed.
+     */
+    if( T != NULL && T != grp->T )
     {
         for( i = 0; i < pre_len; i++ )
             mbedtls_ecp_point_free( &T[i] );
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index fd96258..040aa11 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -19,6 +19,11 @@
  *  This file is part of mbed TLS (https://tls.mbed.org)
  */
 
+#if defined(__linux__)
+/* Ensure that syscall() is available even when compiling with -std=c99 */
+#define _GNU_SOURCE
+#endif
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -45,7 +50,8 @@
 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
 
 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
-    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
+    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
+    !defined(__HAIKU__)
 #error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
 #endif
 
diff --git a/library/error.c b/library/error.c
index 2a85d27..774244b 100644
--- a/library/error.c
+++ b/library/error.c
@@ -73,6 +73,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
@@ -157,6 +165,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
@@ -676,6 +688,22 @@
         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" );
+    if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) )
+        mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" );
+#endif /* MBEDTLS_CHACHA20_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    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" );
+#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" );
@@ -793,6 +821,15 @@
         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" );
+    if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) )
+        mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" );
+#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/hkdf.c b/library/hkdf.c
index d2e55e8..82d8a42 100644
--- a/library/hkdf.c
+++ b/library/hkdf.c
@@ -62,6 +62,11 @@
     {
         size_t hash_len;
 
+        if( salt_len != 0 )
+        {
+            return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
+        }
+
         hash_len = mbedtls_md_get_size( md );
 
         if( hash_len == 0 )
@@ -114,6 +119,10 @@
         n++;
     }
 
+    /*
+     * Per RFC 5869 Section 2.3, okm_len must not exceed
+     * 255 times the hash length
+     */
     if( n > 255 )
     {
         return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
@@ -126,7 +135,10 @@
         goto exit;
     }
 
-    /* RFC 5869 Section 2.3. */
+    /*
+     * Compute T = T(1) | T(2) | T(3) | ... | T(N)
+     * Where T(N) is defined in RFC 5869 Section 2.3
+     */
     for( i = 1; i <= n; i++ )
     {
         size_t num_to_copy;
@@ -150,7 +162,7 @@
             goto exit;
         }
 
-        /* The constant concatenated to the end of each t(n) is a single octet.
+        /* 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 )
diff --git a/library/md5.c b/library/md5.c
index 8238c2b..2a740cd 100644
--- a/library/md5.c
+++ b/library/md5.c
@@ -309,14 +309,6 @@
 }
 #endif
 
-static const unsigned char md5_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
 /*
  * MD5 final digest
  */
@@ -324,26 +316,48 @@
                             unsigned char output[16] )
 {
     int ret;
-    uint32_t last, padn;
+    uint32_t used;
     uint32_t high, low;
-    unsigned char msglen[8];
 
+    /*
+     * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
+     */
+    used = ctx->total[0] & 0x3F;
+
+    ctx->buffer[used++] = 0x80;
+
+    if( used <= 56 )
+    {
+        /* Enough room for padding + length in current block */
+        memset( ctx->buffer + used, 0, 56 - used );
+    }
+    else
+    {
+        /* We'll need an extra block */
+        memset( ctx->buffer + used, 0, 64 - used );
+
+        if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
+            return( ret );
+
+        memset( ctx->buffer, 0, 56 );
+    }
+
+    /*
+     * Add message length
+     */
     high = ( ctx->total[0] >> 29 )
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT32_LE( low,  msglen, 0 );
-    PUT_UINT32_LE( high, msglen, 4 );
+    PUT_UINT32_LE( low,  ctx->buffer, 56 );
+    PUT_UINT32_LE( high, ctx->buffer, 60 );
 
-    last = ctx->total[0] & 0x3F;
-    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+    if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
+        return( ret );
 
-    if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 )
-            return( ret );
-
-    if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 )
-            return( ret );
-
+    /*
+     * Output final state
+     */
     PUT_UINT32_LE( ctx->state[0], output,  0 );
     PUT_UINT32_LE( ctx->state[1], output,  4 );
     PUT_UINT32_LE( ctx->state[2], output,  8 );
diff --git a/library/net_sockets.c b/library/net_sockets.c
index 202da01..816b130 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -19,6 +19,11 @@
  *  This file is part of mbed TLS (https://tls.mbed.org)
  */
 
+/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
+ * be set before config.h, which pulls in glibc's features.h indirectly.
+ * Harmless on other platforms. */
+#define _POSIX_C_SOURCE 200112L
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -28,7 +33,8 @@
 #if defined(MBEDTLS_NET_C)
 
 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
-    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
+    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
+    !defined(__HAIKU__)
 #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
 #endif
 
diff --git a/library/nist_kw.c b/library/nist_kw.c
new file mode 100644
index 0000000..176af9f
--- /dev/null
+++ b/library/nist_kw.c
@@ -0,0 +1,755 @@
+/*
+ *  Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
+ *  only
+ *
+ *  Copyright (C) 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)
+ */
+/*
+ * Definition of Key Wrapping:
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
+ * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
+ * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
+ *
+ * Note: RFC 3394 defines different methodology for intermediate operations for
+ * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_NIST_KW_C)
+
+#include "mbedtls/nist_kw.h"
+#include "mbedtls/platform_util.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+#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 && MBEDTLS_AES_C */
+
+#if !defined(MBEDTLS_NIST_KW_ALT)
+
+#define KW_SEMIBLOCK_LENGTH    8
+#define MIN_SEMIBLOCKS_COUNT   3
+
+/* constant-time buffer comparison */
+static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n )
+{
+    size_t i;
+    volatile const unsigned char *A = (volatile const unsigned char *) a;
+    volatile const unsigned char *B = (volatile const unsigned char *) b;
+    volatile unsigned char diff = 0;
+
+    for( i = 0; i < n; i++ )
+    {
+        /* Read volatile data in order before computing diff.
+         * This avoids IAR compiler warning:
+         * 'the order of volatile accesses is undefined ..' */
+        unsigned char x = A[i], y = B[i];
+        diff |= x ^ y;
+    }
+
+    return( diff );
+}
+
+/*! The 64-bit default integrity check value (ICV) for KW mode. */
+static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
+/*! The 32-bit default integrity check value (ICV) for KWP mode. */
+static const  unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6};
+
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+do {                                                    \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+} while( 0 )
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+do {                                                    \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+} while( 0 )
+#endif
+
+/*
+ * Initialize context
+ */
+void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) );
+}
+
+int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
+                            mbedtls_cipher_id_t cipher,
+                            const unsigned char *key,
+                            unsigned int keybits,
+                            const int is_wrap )
+{
+    int ret;
+    const mbedtls_cipher_info_t *cipher_info;
+
+    cipher_info = mbedtls_cipher_info_from_values( cipher,
+                                                   keybits,
+                                                   MBEDTLS_MODE_ECB );
+    if( cipher_info == NULL )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    if( cipher_info->block_size != 16 )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    /*
+     * SP 800-38F currently defines AES cipher as the only block cipher allowed:
+     * "For KW and KWP, the underlying block cipher shall be approved, and the
+     *  block size shall be 128 bits. Currently, the AES block cipher, with key
+     *  lengths of 128, 192, or 256 bits, is the only block cipher that fits
+     *  this profile."
+     *  Currently we don't support other 128 bit block ciphers for key wrapping,
+     *  such as Camellia and Aria.
+     */
+    if( cipher != MBEDTLS_CIPHER_ID_AES )
+        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+    mbedtls_cipher_free( &ctx->cipher_ctx );
+
+    if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
+        return( ret );
+
+    if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
+                                       is_wrap ? MBEDTLS_ENCRYPT :
+                                                 MBEDTLS_DECRYPT )
+                                                                   ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Free context
+ */
+void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx )
+{
+    mbedtls_cipher_free( &ctx->cipher_ctx );
+    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) );
+}
+
+/*
+ * Helper function for Xoring the uint64_t "t" with the encrypted A.
+ * Defined in NIST SP 800-38F section 6.1
+ */
+static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t )
+{
+    size_t i = 0;
+    for( i = 0; i < sizeof( t ); i++ )
+    {
+        A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff;
+    }
+}
+
+/*
+ * KW-AE as defined in SP 800-38F section 6.2
+ * KWP-AE as defined in SP 800-38F section 6.3
+ */
+int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
+                          mbedtls_nist_kw_mode_t mode,
+                          const unsigned char *input, size_t in_len,
+                          unsigned char *output, size_t *out_len, size_t out_size )
+{
+    int ret = 0;
+    size_t semiblocks = 0;
+    size_t s;
+    size_t olen, padlen = 0;
+    uint64_t t = 0;
+    unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
+    unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
+    unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
+    unsigned char *A = output;
+
+    *out_len = 0;
+    /*
+     * Generate the String to work on
+     */
+    if( mode == MBEDTLS_KW_MODE_KW )
+    {
+        if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
+        {
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+
+        /*
+         * According to SP 800-38F Table 1, the plaintext length for KW
+         * must be between 2 to 2^54-1 semiblocks inclusive.
+         */
+        if( in_len < 16 ||
+#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
+            in_len > 0x1FFFFFFFFFFFFF8 ||
+#endif
+            in_len % KW_SEMIBLOCK_LENGTH != 0 )
+        {
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+
+        memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
+        memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
+    }
+    else
+    {
+        if( in_len % 8 != 0 )
+        {
+            padlen = ( 8 - ( in_len % 8 ) );
+        }
+
+        if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
+        {
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+
+        /*
+         * According to SP 800-38F Table 1, the plaintext length for KWP
+         * must be between 1 and 2^32-1 octets inclusive.
+         */
+        if( in_len < 1
+#if SIZE_MAX > 0xFFFFFFFF
+            || in_len > 0xFFFFFFFF
+#endif
+          )
+        {
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+
+        memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
+        PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
+                       KW_SEMIBLOCK_LENGTH / 2 );
+
+        memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
+        memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
+    }
+    semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
+
+    s = 6 * ( semiblocks - 1 );
+
+    if( mode == MBEDTLS_KW_MODE_KWP
+        && in_len <= KW_SEMIBLOCK_LENGTH )
+    {
+        memcpy( inbuff, output, 16 );
+        ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+                                     inbuff, 16, output, &olen );
+        if( ret != 0 )
+            goto cleanup;
+    }
+    else
+    {
+        /*
+         * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
+         */
+        if( semiblocks < MIN_SEMIBLOCKS_COUNT )
+        {
+            ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+            goto cleanup;
+        }
+
+        /* Calculate intermediate values */
+        for( t = 1; t <= s; t++ )
+        {
+            memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
+            memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
+
+            ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+                                         inbuff, 16, outbuff, &olen );
+            if( ret != 0 )
+                goto cleanup;
+
+            memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
+            calc_a_xor_t( A, t );
+
+            memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
+            R2 += KW_SEMIBLOCK_LENGTH;
+            if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
+                R2 = output + KW_SEMIBLOCK_LENGTH;
+        }
+    }
+
+    *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
+
+cleanup:
+
+    if( ret != 0)
+    {
+        memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
+    }
+    mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
+    mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
+    mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
+    return( ret );
+}
+
+/*
+ * W-1 function as defined in RFC 3394 section 2.2.2
+ * This function assumes the following:
+ * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
+ * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
+ * 3. Minimal number of semiblocks is 3.
+ * 4. A is a buffer to hold the first semiblock of the input buffer.
+ */
+static int unwrap( mbedtls_nist_kw_context *ctx,
+                   const unsigned char *input, size_t semiblocks,
+                   unsigned char A[KW_SEMIBLOCK_LENGTH],
+                   unsigned char *output, size_t* out_len )
+{
+    int ret = 0;
+    const size_t s = 6 * ( semiblocks - 1 );
+    size_t olen;
+    uint64_t t = 0;
+    unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
+    unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
+    unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
+    *out_len = 0;
+
+    if( semiblocks < MIN_SEMIBLOCKS_COUNT )
+    {
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    }
+
+    memcpy( A, input, KW_SEMIBLOCK_LENGTH );
+    memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+
+    /* Calculate intermediate values */
+    for( t = s; t >= 1; t-- )
+    {
+        calc_a_xor_t( A, t );
+
+        memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
+        memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
+
+        ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+                                     inbuff, 16, outbuff, &olen );
+        if( ret != 0 )
+            goto cleanup;
+
+        memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
+
+        /* Set R as LSB64 of outbuff */
+        memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
+
+        if( R == output )
+            R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
+        else
+            R -= KW_SEMIBLOCK_LENGTH;
+    }
+
+    *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
+
+cleanup:
+    if( ret != 0)
+        memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+    mbedtls_platform_zeroize( inbuff, sizeof( inbuff )  );
+    mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
+
+    return( ret );
+}
+
+/*
+ * KW-AD as defined in SP 800-38F section 6.2
+ * KWP-AD as defined in SP 800-38F section 6.3
+ */
+int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
+                            mbedtls_nist_kw_mode_t mode,
+                            const unsigned char *input, size_t in_len,
+                            unsigned char *output, size_t *out_len, size_t out_size )
+{
+    int ret = 0;
+    size_t i, olen;
+    unsigned char A[KW_SEMIBLOCK_LENGTH];
+    unsigned char diff, bad_padding = 0;
+
+    *out_len = 0;
+    if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
+    {
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    }
+
+    if( mode == MBEDTLS_KW_MODE_KW )
+    {
+        /*
+         * According to SP 800-38F Table 1, the ciphertext length for KW
+         * must be between 3 to 2^54 semiblocks inclusive.
+         */
+        if( in_len < 24 ||
+#if SIZE_MAX > 0x200000000000000
+            in_len > 0x200000000000000 ||
+#endif
+            in_len % KW_SEMIBLOCK_LENGTH != 0 )
+        {
+            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+
+        ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
+                      A, output, out_len );
+        if( ret != 0 )
+            goto cleanup;
+
+        /* Check ICV in "constant-time" */
+        diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
+
+        if( diff != 0 )
+        {
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+            goto cleanup;
+        }
+
+    }
+    else if( mode == MBEDTLS_KW_MODE_KWP )
+    {
+        size_t padlen = 0;
+        uint32_t Plen;
+        /*
+         * According to SP 800-38F Table 1, the ciphertext length for KWP
+         * must be between 2 to 2^29 semiblocks inclusive.
+         */
+        if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
+#if SIZE_MAX > 0x100000000
+            in_len > 0x100000000 ||
+#endif
+            in_len % KW_SEMIBLOCK_LENGTH != 0 )
+        {
+            return(  MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        }
+
+        if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
+        {
+            unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
+            ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+                                         input, 16, outbuff, &olen );
+            if( ret != 0 )
+                goto cleanup;
+
+            memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
+            memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
+            mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
+            *out_len = KW_SEMIBLOCK_LENGTH;
+        }
+        else
+        {
+            /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */
+            ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
+                          A, output, out_len );
+            if( ret != 0 )
+                goto cleanup;
+        }
+
+        /* Check ICV in "constant-time" */
+        diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
+
+        if( diff != 0 )
+        {
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+        }
+
+        GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
+
+        /*
+         * Plen is the length of the plaintext, when the input is valid.
+         * If Plen is larger than the plaintext and padding, padlen will be
+         * larger than 8, because of the type wrap around.
+         */
+        padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
+        if ( padlen > 7 )
+        {
+            padlen &= 7;
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+        }
+
+        /* Check padding in "constant-time" */
+        for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
+        {
+             if( i >= KW_SEMIBLOCK_LENGTH - padlen )
+                 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
+             else
+                 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
+        }
+
+        if( diff != 0 )
+        {
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+        }
+
+        if( ret != 0 )
+        {
+            goto cleanup;
+        }
+        memset( output + Plen, 0, padlen );
+        *out_len = Plen;
+    }
+    else
+    {
+        ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+        goto cleanup;
+    }
+
+cleanup:
+    if( ret != 0 )
+    {
+        memset( output, 0, *out_len );
+        *out_len = 0;
+    }
+
+    mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
+    mbedtls_platform_zeroize( &diff, sizeof( diff ) );
+    mbedtls_platform_zeroize( A, sizeof( A ) );
+    mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
+    return( ret );
+}
+
+#endif /* !MBEDTLS_NIST_KW_ALT */
+
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+
+#define KW_TESTS 3
+
+/*
+ * Test vectors taken from NIST
+ * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
+ */
+static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
+
+static const unsigned char kw_key[KW_TESTS][32] = {
+    { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
+      0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
+    { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
+      0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
+      0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
+    { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
+      0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
+      0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
+      0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
+};
+
+static const unsigned char kw_msg[KW_TESTS][40] = {
+    { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
+      0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
+    { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
+      0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
+      0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
+      0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
+      0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
+    { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
+      0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
+      0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
+};
+
+static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
+static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
+static const unsigned char kw_res[KW_TESTS][48] = {
+    { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
+      0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
+      0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
+    { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
+      0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
+      0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
+      0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
+      0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
+      0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
+    { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
+      0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
+      0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
+      0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
+};
+
+static const unsigned char kwp_key[KW_TESTS][32] = {
+    { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
+      0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
+    { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
+      0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
+      0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
+    { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
+      0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
+      0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
+      0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
+};
+
+static const unsigned char kwp_msg[KW_TESTS][31] = {
+    { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
+      0x96 },
+    { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
+      0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
+      0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
+      0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
+    { 0xd1 }
+};
+static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
+
+static const unsigned char kwp_res[KW_TESTS][48] = {
+    { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
+      0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
+      0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
+    { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
+      0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
+      0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
+      0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
+      0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
+    { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
+      0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }
+};
+static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
+
+int mbedtls_nist_kw_self_test( int verbose )
+{
+    mbedtls_nist_kw_context ctx;
+    unsigned char out[48];
+    size_t olen;
+    int i;
+    int ret = 0;
+    mbedtls_nist_kw_init( &ctx );
+
+    for( i = 0; i < KW_TESTS; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  KW-AES-%u ", (unsigned int) key_len[i] * 8 );
+
+        ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+                                      kw_key[i], key_len[i] * 8, 1 );
+        if( ret != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "  KW: setup failed " );
+
+            goto end;
+        }
+
+        ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
+                                    kw_msg_len[i], out, &olen, sizeof( out ) );
+        if( ret != 0 || kw_out_len[i] != olen ||
+            memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed. ");
+
+            ret = 1;
+            goto end;
+        }
+
+        if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+                                            kw_key[i], key_len[i] * 8, 0 ) )
+              != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "  KW: setup failed ");
+
+            goto end;
+        }
+
+        ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
+                                      out, olen, out, &olen, sizeof( out ) );
+
+        if( ret != 0 || olen != kw_msg_len[i] ||
+            memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed\n" );
+
+            ret = 1;
+            goto end;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( " passed\n" );
+    }
+
+    for( i = 0; i < KW_TESTS; i++ )
+    {
+        olen = sizeof( out );
+        if( verbose != 0 )
+            mbedtls_printf( "  KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
+
+        ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
+                                      key_len[i] * 8, 1 );
+        if( ret  != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "  KWP: setup failed " );
+
+            goto end;
+        }
+        ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
+                                    kwp_msg_len[i], out, &olen, sizeof( out ) );
+
+        if( ret != 0 || kwp_out_len[i] != olen ||
+            memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed. ");
+
+            ret = 1;
+            goto end;
+        }
+
+        if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+                                            kwp_key[i], key_len[i] * 8, 0 ) )
+              != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "  KWP: setup failed ");
+
+            goto end;
+        }
+
+        ret = mbedtls_nist_kw_unwrap(  &ctx, MBEDTLS_KW_MODE_KWP, out,
+                                       olen, out, &olen, sizeof( out ) );
+
+        if( ret != 0 || olen != kwp_msg_len[i] ||
+            memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed. ");
+
+            ret = 1;
+            goto end;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( " passed\n" );
+    }
+end:
+    mbedtls_nist_kw_free( &ctx );
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+
+#endif /* MBEDTLS_NIST_KW_C */
diff --git a/library/pkparse.c b/library/pkparse.c
index ccb7f54..d6ac987 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -1261,7 +1261,6 @@
         return( ret );
 #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
 #else
-    ((void) ret);
     ((void) pwd);
     ((void) pwdlen);
 #endif /* MBEDTLS_PEM_PARSE_C */
diff --git a/library/poly1305.c b/library/poly1305.c
new file mode 100644
index 0000000..e22d3af
--- /dev/null
+++ b/library/poly1305.c
@@ -0,0 +1,563 @@
+/**
+ * \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)
+
+#include "mbedtls/poly1305.h"
+#include "mbedtls/platform_util.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_POLY1305_ALT)
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#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 )  \
+    )
+
+/*
+ * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.
+ * However we provided an alternative for platforms without such a multiplier.
+ */
+#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
+static uint64_t mul64( uint32_t a, uint32_t b )
+{
+    /* a = al + 2**16 ah, b = bl + 2**16 bh */
+    const uint16_t al = (uint16_t) a;
+    const uint16_t bl = (uint16_t) b;
+    const uint16_t ah = a >> 16;
+    const uint16_t bh = b >> 16;
+
+    /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */
+    const uint32_t lo = (uint32_t) al * bl;
+    const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh;
+    const uint32_t hi = (uint32_t) ah * bh;
+
+    return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) );
+}
+#else
+static inline uint64_t mul64( uint32_t a, uint32_t b )
+{
+    return( (uint64_t) a * b );
+}
+#endif
+
+
+/**
+ * \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 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++ )
+    {
+        /* The input block is treated as a 128-bit little-endian integer */
+        d0   = BYTES_TO_U32_LE( input, offset + 0  );
+        d1   = BYTES_TO_U32_LE( input, offset + 4  );
+        d2   = BYTES_TO_U32_LE( input, offset + 8  );
+        d3   = BYTES_TO_U32_LE( input, offset + 12 );
+
+        /* Compute: acc += (padded) block as a 130-bit integer */
+        d0  += (uint64_t) acc0;
+        d1  += (uint64_t) acc1 + ( d0 >> 32U );
+        d2  += (uint64_t) acc2 + ( d1 >> 32U );
+        d3  += (uint64_t) acc3 + ( 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 = mul64( acc0, r0  ) +
+             mul64( acc1, rs3 ) +
+             mul64( acc2, rs2 ) +
+             mul64( acc3, rs1 );
+        d1 = mul64( acc0, r1  ) +
+             mul64( acc1, r0  ) +
+             mul64( acc2, rs3 ) +
+             mul64( acc3, rs2 ) +
+             mul64( acc4, rs1 );
+        d2 = mul64( acc0, r2  ) +
+             mul64( acc1, r1  ) +
+             mul64( acc2, r0  ) +
+             mul64( acc3, rs3 ) +
+             mul64( acc4, rs2 );
+        d3 = mul64( acc0, r3  ) +
+             mul64( acc1, r2  ) +
+             mul64( acc2, r1  ) +
+             mul64( acc3, r0  ) +
+             mul64( 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 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 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_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
+    }
+}
+
+void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx )
+{
+    if( ctx != NULL )
+    {
+        mbedtls_platform_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_platform_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;
+
+            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;
+
+        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 );
+
+        poly1305_process( ctx, 1U,          /* Process 1 block */
+                          ctx->queue, 0U ); /* Already padded above */
+    }
+
+    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 ret;
+
+    mbedtls_poly1305_init( &ctx );
+
+    ret = mbedtls_poly1305_starts( &ctx, key );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = mbedtls_poly1305_update( &ctx, input, ilen );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = mbedtls_poly1305_finish( &ctx, mac );
+
+cleanup:
+    mbedtls_poly1305_free( &ctx );
+    return( ret );
+}
+
+#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 ret;
+
+    for( i = 0U; i < 2U; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  Poly1305 test %u ", i );
+
+        ret = mbedtls_poly1305_mac( test_keys[i],
+                                    test_data[i],
+                                    test_data_len[i],
+                                    mac );
+        ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
+
+        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/sha1.c b/library/sha1.c
index 1587de4..bab6087 100644
--- a/library/sha1.c
+++ b/library/sha1.c
@@ -342,14 +342,6 @@
 }
 #endif
 
-static const unsigned char sha1_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
 /*
  * SHA-1 final digest
  */
@@ -357,25 +349,48 @@
                              unsigned char output[20] )
 {
     int ret;
-    uint32_t last, padn;
+    uint32_t used;
     uint32_t high, low;
-    unsigned char msglen[8];
 
+    /*
+     * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
+     */
+    used = ctx->total[0] & 0x3F;
+
+    ctx->buffer[used++] = 0x80;
+
+    if( used <= 56 )
+    {
+        /* Enough room for padding + length in current block */
+        memset( ctx->buffer + used, 0, 56 - used );
+    }
+    else
+    {
+        /* We'll need an extra block */
+        memset( ctx->buffer + used, 0, 64 - used );
+
+        if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
+            return( ret );
+
+        memset( ctx->buffer, 0, 56 );
+    }
+
+    /*
+     * Add message length
+     */
     high = ( ctx->total[0] >> 29 )
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT32_BE( high, msglen, 0 );
-    PUT_UINT32_BE( low,  msglen, 4 );
+    PUT_UINT32_BE( high, ctx->buffer, 56 );
+    PUT_UINT32_BE( low,  ctx->buffer, 60 );
 
-    last = ctx->total[0] & 0x3F;
-    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
-    if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 )
-        return( ret );
-    if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 )
+    if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
         return( ret );
 
+    /*
+     * Output final state
+     */
     PUT_UINT32_BE( ctx->state[0], output,  0 );
     PUT_UINT32_BE( ctx->state[1], output,  4 );
     PUT_UINT32_BE( ctx->state[2], output,  8 );
diff --git a/library/sha256.c b/library/sha256.c
index 695485d..dbb4a89 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -311,14 +311,6 @@
 }
 #endif
 
-static const unsigned char sha256_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
 /*
  * SHA-256 final digest
  */
@@ -326,26 +318,48 @@
                                unsigned char output[32] )
 {
     int ret;
-    uint32_t last, padn;
+    uint32_t used;
     uint32_t high, low;
-    unsigned char msglen[8];
 
+    /*
+     * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
+     */
+    used = ctx->total[0] & 0x3F;
+
+    ctx->buffer[used++] = 0x80;
+
+    if( used <= 56 )
+    {
+        /* Enough room for padding + length in current block */
+        memset( ctx->buffer + used, 0, 56 - used );
+    }
+    else
+    {
+        /* We'll need an extra block */
+        memset( ctx->buffer + used, 0, 64 - used );
+
+        if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
+            return( ret );
+
+        memset( ctx->buffer, 0, 56 );
+    }
+
+    /*
+     * Add message length
+     */
     high = ( ctx->total[0] >> 29 )
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT32_BE( high, msglen, 0 );
-    PUT_UINT32_BE( low,  msglen, 4 );
+    PUT_UINT32_BE( high, ctx->buffer, 56 );
+    PUT_UINT32_BE( low,  ctx->buffer, 60 );
 
-    last = ctx->total[0] & 0x3F;
-    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
-    if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 )
+    if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
         return( ret );
 
-    if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 )
-        return( ret );
-
+    /*
+     * Output final state
+     */
     PUT_UINT32_BE( ctx->state[0], output,  0 );
     PUT_UINT32_BE( ctx->state[1], output,  4 );
     PUT_UINT32_BE( ctx->state[2], output,  8 );
diff --git a/library/sha512.c b/library/sha512.c
index 6de94e9..a9440e8 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -341,18 +341,6 @@
 }
 #endif
 
-static const unsigned char sha512_padding[128] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
 /*
  * SHA-512 final digest
  */
@@ -360,26 +348,48 @@
                                unsigned char output[64] )
 {
     int ret;
-    size_t last, padn;
+    unsigned used;
     uint64_t high, low;
-    unsigned char msglen[16];
 
+    /*
+     * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
+     */
+    used = ctx->total[0] & 0x7F;
+
+    ctx->buffer[used++] = 0x80;
+
+    if( used <= 112 )
+    {
+        /* Enough room for padding + length in current block */
+        memset( ctx->buffer + used, 0, 112 - used );
+    }
+    else
+    {
+        /* We'll need an extra block */
+        memset( ctx->buffer + used, 0, 128 - used );
+
+        if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
+            return( ret );
+
+        memset( ctx->buffer, 0, 112 );
+    }
+
+    /*
+     * Add message length
+     */
     high = ( ctx->total[0] >> 61 )
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT64_BE( high, msglen, 0 );
-    PUT_UINT64_BE( low,  msglen, 8 );
+    PUT_UINT64_BE( high, ctx->buffer, 112 );
+    PUT_UINT64_BE( low,  ctx->buffer, 120 );
 
-    last = (size_t)( ctx->total[0] & 0x7F );
-    padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
+    if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
+        return( ret );
 
-    if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 )
-            return( ret );
-
-    if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 )
-            return( ret );
-
+    /*
+     * Output final state
+     */
     PUT_UINT64_BE( ctx->state[0], output,  0 );
     PUT_UINT64_BE( ctx->state[1], output,  8 );
     PUT_UINT64_BE( ctx->state[2], output, 16 );
diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
index dc4f0bb..745474e 100644
--- a/library/ssl_ciphersuites.c
+++ b/library/ssl_ciphersuites.c
@@ -47,7 +47,7 @@
  * 1. By key exchange:
  *    Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK
  * 2. By key length and cipher:
- *    AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES
+ *    ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES
  * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8
  * 4. By hash function used when relevant
  * 5. By key exchange/auth again: EC > non-EC
@@ -57,6 +57,11 @@
 #if defined(MBEDTLS_SSL_CIPHERSUITES)
     MBEDTLS_SSL_CIPHERSUITES,
 #else
+    /* Chacha-Poly ephemeral suites */
+    MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+    MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+    MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+
     /* All AES-256 ephemeral suites */
     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
     MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
@@ -127,6 +132,8 @@
     MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
 
     /* The PSK ephemeral suites */
+    MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+    MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
     MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
     MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
@@ -227,6 +234,7 @@
     MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
 
     /* The RSA PSK suites */
+    MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
     MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
@@ -246,6 +254,7 @@
     MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
 
     /* The PSK suites */
+    MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
     MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
     MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
     MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
@@ -312,6 +321,75 @@
 
 static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 {
+#if defined(MBEDTLS_CHACHAPOLY_C) && \
+    defined(MBEDTLS_SHA256_C) && \
+    defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
+    { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+      "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
+      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+      "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
+      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+      "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
+      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_DHE_RSA,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+    { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
+      "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256",
+      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_PSK,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+      "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
+      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+      "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
+      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_DHE_PSK,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      0 },
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
+      "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256",
+      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_RSA_PSK,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
+      0 },
+#endif
+#endif /* MBEDTLS_CHACHAPOLY_C &&
+          MBEDTLS_SHA256_C &&
+          MBEDTLS_SSL_PROTO_TLS1_2 */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
 #if defined(MBEDTLS_SHA1_C)
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index ad11292..321d636 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -57,7 +57,7 @@
                                     size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t hostname_len;
 
     *olen = 0;
@@ -127,7 +127,7 @@
                                          size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
@@ -171,7 +171,7 @@
                                                 size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t sig_alg_len = 0;
     const int *md;
 #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
@@ -256,7 +256,7 @@
                                                      size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     unsigned char *elliptic_curve_list = p + 6;
     size_t elliptic_curve_len = 0;
     const mbedtls_ecp_curve_info *info;
@@ -329,7 +329,7 @@
                                                    size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
@@ -362,7 +362,7 @@
 {
     int ret;
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t kkpp_len;
 
     *olen = 0;
@@ -439,7 +439,7 @@
                                                size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
@@ -472,7 +472,7 @@
                                           unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
@@ -504,7 +504,7 @@
                                        unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
@@ -538,7 +538,7 @@
                                        unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
 
     *olen = 0;
 
@@ -572,7 +572,7 @@
                                           unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t tlen = ssl->session_negotiate->ticket_len;
 
     *olen = 0;
@@ -616,7 +616,7 @@
                                 unsigned char *buf, size_t *olen )
 {
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t alpnlen = 0;
     const char **cur;
 
@@ -1259,14 +1259,14 @@
     size_t list_size;
     const unsigned char *p;
 
-    list_size = buf[0];
-    if( list_size + 1 != len )
+    if( len == 0 || (size_t)( buf[0] + 1 ) != len )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                         MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
+    list_size = buf[0];
 
     p = buf + 1;
     while( list_size > 0 )
@@ -2129,7 +2129,7 @@
     size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
     unsigned char *p = ssl->handshake->premaster + pms_offset;
 
-    if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN )
+    if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) );
         return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
@@ -2172,7 +2172,7 @@
     if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
                             p, ssl->handshake->pmslen,
                             ssl->out_msg + offset + len_bytes, olen,
-                            MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes,
+                            MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
                             ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret );
@@ -2721,7 +2721,7 @@
      * 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 )
+    if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -2938,7 +2938,7 @@
         i = 4;
         n = ssl->conf->psk_identity_len;
 
-        if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
+        if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or "
                                         "SSL buffer too short" ) );
@@ -2974,7 +2974,7 @@
              */
             n = ssl->handshake->dhm_ctx.len;
 
-            if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
+            if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long"
                                             " or SSL buffer too short" ) );
@@ -3003,7 +3003,7 @@
              * ClientECDiffieHellmanPublic public;
              */
             ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n,
-                    &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i,
+                    &ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i,
                     ssl->conf->f_rng, ssl->conf->p_rng );
             if( ret != 0 )
             {
@@ -3044,7 +3044,7 @@
         i = 4;
 
         ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
-                ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n,
+                ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n,
                 ssl->conf->f_rng, ssl->conf->p_rng );
         if( ret != 0 )
         {
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 91079f1..2872f1f 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -91,6 +91,13 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
 
+    if( len < 2 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
     servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
     if( servername_list_size + 2 != len )
     {
@@ -101,7 +108,7 @@
     }
 
     p = buf + 2;
-    while( servername_list_size > 0 )
+    while( servername_list_size > 2 )
     {
         hostname_len = ( ( p[1] << 8 ) | p[2] );
         if( hostname_len + 3 > servername_list_size )
@@ -205,6 +212,12 @@
     mbedtls_md_type_t md_cur;
     mbedtls_pk_type_t sig_cur;
 
+    if ( len < 2 ) {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
     sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
     if( sig_alg_list_size + 2 != len ||
         sig_alg_list_size % 2 != 0 )
@@ -273,6 +286,12 @@
     const unsigned char *p;
     const mbedtls_ecp_curve_info *curve_info, **curves;
 
+    if ( len < 2 ) {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
     list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
     if( list_size + 2 != len ||
         list_size % 2 != 0 )
@@ -332,14 +351,14 @@
     size_t list_size;
     const unsigned char *p;
 
-    list_size = buf[0];
-    if( list_size + 1 != len )
+    if( len == 0 || (size_t)( buf[0] + 1 ) != len )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                         MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
         return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
     }
+    list_size = buf[0];
 
     p = buf + 1;
     while( list_size > 0 )
@@ -1303,7 +1322,7 @@
     else
 #endif
     {
-        if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
+        if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
             return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
@@ -1656,10 +1675,16 @@
 
         while( ext_len != 0 )
         {
-            unsigned int ext_id   = ( ( ext[0] <<  8 )
-                                    | ( ext[1]       ) );
-            unsigned int ext_size = ( ( ext[2] <<  8 )
-                                    | ( ext[3]       ) );
+            unsigned int ext_id;
+            unsigned int ext_size;
+            if ( ext_len < 4 ) {
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                               MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
+                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+            }
+            ext_id   = ( ( ext[0] <<  8 ) | ( ext[1] ) );
+            ext_size = ( ( ext[2] <<  8 ) | ( ext[3] ) );
 
             if( ext_size + 4 > ext_len )
             {
@@ -2235,7 +2260,7 @@
 {
     int ret;
     unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     size_t kkpp_len;
 
     *olen = 0;
@@ -2342,7 +2367,7 @@
     cookie_len_byte = p++;
 
     if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie,
-                                     &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN,
+                                     &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,
                                      ssl->cli_id, ssl->cli_id_len ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret );
@@ -2642,7 +2667,7 @@
     size_t dn_size, total_dn_size; /* excluding length bytes */
     size_t ct_len, sa_len; /* including length bytes */
     unsigned char *buf, *p;
-    const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
+    const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
     const mbedtls_x509_crt *crt;
     int authmode;
 
@@ -2843,7 +2868,7 @@
      * ssl_write_server_key_exchange also takes care of incrementing
      * ssl->out_msglen. */
     unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
-    size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_MAX_CONTENT_LEN
+    size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN
                            - sig_start );
     int ret = ssl->conf->f_async_resume( ssl,
                                          sig_start, signature_len, sig_max_len );
@@ -2897,7 +2922,7 @@
         ret = mbedtls_ecjpake_write_round_two(
             &ssl->handshake->ecjpake_ctx,
             ssl->out_msg + ssl->out_msglen,
-            MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen, &len,
+            MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len,
             ssl->conf->f_rng, ssl->conf->p_rng );
         if( ret != 0 )
         {
@@ -3024,7 +3049,7 @@
         if( ( ret = mbedtls_ecdh_make_params(
                   &ssl->handshake->ecdh_ctx, &len,
                   ssl->out_msg + ssl->out_msglen,
-                  MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen,
+                  MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen,
                   ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
@@ -3441,6 +3466,10 @@
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
     if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
     {
+        if ( p + 2 > end ) {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
+            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
+        }
         if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
             *p++ != ( ( len      ) & 0xFF ) )
         {
@@ -4175,7 +4204,7 @@
     if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket,
                                 ssl->session_negotiate,
                                 ssl->out_msg + 10,
-                                ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN,
+                                ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
                                 &tlen, &lifetime ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index e5119fc..91f96c8 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -141,14 +141,24 @@
  *    } MaxFragmentLength;
  * and we add 0 -> extension unused
  */
-static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] =
+static unsigned int ssl_mfl_code_to_length( int mfl )
 {
-    MBEDTLS_SSL_MAX_CONTENT_LEN,    /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */
-    512,                    /* MBEDTLS_SSL_MAX_FRAG_LEN_512  */
-    1024,                   /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */
-    2048,                   /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */
-    4096,                   /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */
-};
+    switch( mfl )
+    {
+    case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
+        return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN );
+    case MBEDTLS_SSL_MAX_FRAG_LEN_512:
+        return 512;
+    case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
+        return 1024;
+    case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
+        return 2048;
+    case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
+        return 4096;
+    default:
+        return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN );
+    }
+}
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
 #if defined(MBEDTLS_SSL_CLI_C)
@@ -688,18 +698,32 @@
     transform->keylen = cipher_info->key_bitlen / 8;
 
     if( cipher_info->mode == MBEDTLS_MODE_GCM ||
-        cipher_info->mode == MBEDTLS_MODE_CCM )
+        cipher_info->mode == MBEDTLS_MODE_CCM ||
+        cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
     {
+        size_t taglen, explicit_ivlen;
+
         transform->maclen = 0;
         mac_key_len = 0;
 
+        /* All modes haves 96-bit IVs;
+         * GCM and CCM has 4 implicit and 8 explicit bytes
+         * ChachaPoly has all 12 bytes implicit
+         */
         transform->ivlen = 12;
-        transform->fixed_ivlen = 4;
+        if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
+            transform->fixed_ivlen = 12;
+        else
+            transform->fixed_ivlen = 4;
 
-        /* Minimum length is expicit IV + tag */
-        transform->minlen = transform->ivlen - transform->fixed_ivlen
-                            + ( transform->ciphersuite_info->flags &
-                                MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 );
+        /* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */
+        taglen = transform->ciphersuite_info->flags &
+                  MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
+
+
+        /* Minimum length of encrypted record */
+        explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
+        transform->minlen = explicit_ivlen + taglen;
     }
     else
     {
@@ -956,11 +980,11 @@
         if( ssl->compress_buf == NULL )
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) );
-            ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN );
+            ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
             if( ssl->compress_buf == NULL )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
-                                    MBEDTLS_SSL_BUFFER_LEN ) );
+                                    MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) );
                 return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
             }
         }
@@ -1151,6 +1175,9 @@
          * other_secret already set by the ClientKeyExchange message,
          * and is 48 bytes long
          */
+        if( end - p < 2 )
+            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
         *p++ = 0;
         *p++ = 48;
         p += 48;
@@ -1276,6 +1303,27 @@
 #define SSL_SOME_MODES_USE_MAC
 #endif
 
+/* The function below is only used in the Lucky 13 counter-measure in
+ * ssl_decrypt_buf(). These are the defines that guard the call site. */
+#if defined(SSL_SOME_MODES_USE_MAC) && \
+    ( defined(MBEDTLS_SSL_PROTO_TLS1) || \
+      defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+      defined(MBEDTLS_SSL_PROTO_TLS1_2) )
+/* This function makes sure every byte in the memory region is accessed
+ * (in ascending addresses order) */
+static void ssl_read_memory( unsigned char *p, size_t len )
+{
+    unsigned char acc = 0;
+    volatile unsigned char force;
+
+    for( ; len != 0; p++, len-- )
+        acc ^= *p;
+
+    force = acc;
+    (void) force;
+}
+#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */
+
 /*
  * Encryption/decryption functions
  */
@@ -1297,11 +1345,11 @@
     MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
                       ssl->out_msg, ssl->out_msglen );
 
-    if( ssl->out_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
+    if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
                                     (unsigned) ssl->out_msglen,
-                                    MBEDTLS_SSL_MAX_CONTENT_LEN ) );
+                                    MBEDTLS_SSL_OUT_CONTENT_LEN ) );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
 
@@ -1394,17 +1442,26 @@
     }
     else
 #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_GCM_C) || \
+    defined(MBEDTLS_CCM_C) || \
+    defined(MBEDTLS_CHACHAPOLY_C)
     if( mode == MBEDTLS_MODE_GCM ||
-        mode == MBEDTLS_MODE_CCM )
+        mode == MBEDTLS_MODE_CCM ||
+        mode == MBEDTLS_MODE_CHACHAPOLY )
     {
         int ret;
         size_t enc_msglen, olen;
         unsigned char *enc_msg;
         unsigned char add_data[13];
-        unsigned char taglen = ssl->transform_out->ciphersuite_info->flags &
+        unsigned char iv[12];
+        mbedtls_ssl_transform *transform = ssl->transform_out;
+        unsigned char taglen = transform->ciphersuite_info->flags &
                                MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
+        size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
 
+        /*
+         * Prepare additional authenticated data
+         */
         memcpy( add_data, ssl->out_ctr, 8 );
         add_data[8]  = ssl->out_msgtype;
         mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
@@ -1412,44 +1469,57 @@
         add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF;
         add_data[12] = ssl->out_msglen & 0xFF;
 
-        MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
-                       add_data, 13 );
+        MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 );
 
         /*
          * Generate IV
          */
-        if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 )
+        if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
+        {
+            /* GCM and CCM: fixed || explicit (=seqnum) */
+            memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
+            memcpy( iv + transform->fixed_ivlen, ssl->out_ctr, 8 );
+            memcpy( ssl->out_iv, ssl->out_ctr, 8 );
+
+        }
+        else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
+        {
+            /* ChachaPoly: fixed XOR sequence number */
+            unsigned char i;
+
+            memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
+
+            for( i = 0; i < 8; i++ )
+                iv[i+4] ^= ssl->out_ctr[i];
+        }
+        else
         {
             /* Reminder if we ever add an AEAD mode with a different size */
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
         }
 
-        memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
-                             ssl->out_ctr, 8 );
-        memcpy( ssl->out_iv, ssl->out_ctr, 8 );
-
-        MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv,
-                ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+        MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
+                                  iv, transform->ivlen );
+        MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
+                                  ssl->out_iv, explicit_ivlen );
 
         /*
-         * Fix pointer positions and message length with added IV
+         * Fix message length with added IV
          */
         enc_msg = ssl->out_msg;
         enc_msglen = ssl->out_msglen;
-        ssl->out_msglen += ssl->transform_out->ivlen -
-                           ssl->transform_out->fixed_ivlen;
+        ssl->out_msglen += explicit_ivlen;
 
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
-                            "including %d bytes of padding",
-                       ssl->out_msglen, 0 ) );
+                                    "including 0 bytes of padding",
+                                    ssl->out_msglen ) );
 
         /*
          * Encrypt and authenticate
          */
-        if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc,
-                                         ssl->transform_out->iv_enc,
-                                         ssl->transform_out->ivlen,
+        if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc,
+                                         iv, transform->ivlen,
                                          add_data, 13,
                                          enc_msg, enc_msglen,
                                          enc_msg, &olen,
@@ -1609,7 +1679,6 @@
 
 static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
 {
-    size_t i;
     mbedtls_cipher_mode_t mode;
     int auth_done = 0;
 #if defined(SSL_SOME_MODES_USE_MAC)
@@ -1659,20 +1728,27 @@
     }
     else
 #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_GCM_C) || \
+    defined(MBEDTLS_CCM_C) || \
+    defined(MBEDTLS_CHACHAPOLY_C)
     if( mode == MBEDTLS_MODE_GCM ||
-        mode == MBEDTLS_MODE_CCM )
+        mode == MBEDTLS_MODE_CCM ||
+        mode == MBEDTLS_MODE_CHACHAPOLY )
     {
         int ret;
         size_t dec_msglen, olen;
         unsigned char *dec_msg;
         unsigned char *dec_msg_result;
         unsigned char add_data[13];
-        unsigned char taglen = ssl->transform_in->ciphersuite_info->flags &
+        unsigned char iv[12];
+        mbedtls_ssl_transform *transform = ssl->transform_in;
+        unsigned char taglen = transform->ciphersuite_info->flags &
                                MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
-        size_t explicit_iv_len = ssl->transform_in->ivlen -
-                                 ssl->transform_in->fixed_ivlen;
+        size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
 
+        /*
+         * Compute and update sizes
+         */
         if( ssl->in_msglen < explicit_iv_len + taglen )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
@@ -1686,6 +1762,9 @@
         dec_msg_result = ssl->in_msg;
         ssl->in_msglen = dec_msglen;
 
+        /*
+         * Prepare additional authenticated data
+         */
         memcpy( add_data, ssl->in_ctr, 8 );
         add_data[8]  = ssl->in_msgtype;
         mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
@@ -1693,23 +1772,43 @@
         add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
         add_data[12] = ssl->in_msglen & 0xFF;
 
-        MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
-                       add_data, 13 );
+        MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 );
 
-        memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen,
-                ssl->in_iv,
-                ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen );
+        /*
+         * Prepare IV
+         */
+        if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
+        {
+            /* GCM and CCM: fixed || explicit (transmitted) */
+            memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
+            memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 );
 
-        MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec,
-                                     ssl->transform_in->ivlen );
+        }
+        else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
+        {
+            /* ChachaPoly: fixed XOR sequence number */
+            unsigned char i;
+
+            memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
+
+            for( i = 0; i < 8; i++ )
+                iv[i+4] ^= ssl->in_ctr[i];
+        }
+        else
+        {
+            /* Reminder if we ever add an AEAD mode with a different size */
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
         MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen );
 
         /*
          * Decrypt and authenticate
          */
         if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec,
-                                         ssl->transform_in->iv_dec,
-                                         ssl->transform_in->ivlen,
+                                         iv, transform->ivlen,
                                          add_data, 13,
                                          dec_msg, dec_msglen,
                                          dec_msg_result, &olen,
@@ -1827,6 +1926,7 @@
          */
         if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
         {
+            unsigned char i;
             dec_msglen -= ssl->transform_in->ivlen;
             ssl->in_msglen -= ssl->transform_in->ivlen;
 
@@ -1900,27 +2000,28 @@
              * and fake check up to 256 bytes of padding
              */
             size_t pad_count = 0, real_count = 1;
-            size_t padding_idx = ssl->in_msglen - padlen - 1;
+            size_t padding_idx = ssl->in_msglen - padlen;
+            size_t i;
 
             /*
              * Padding is guaranteed to be incorrect if:
-             *   1. padlen >= ssl->in_msglen
+             *   1. padlen > ssl->in_msglen
              *
-             *   2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN +
+             *   2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN +
              *                     ssl->transform_in->maclen
              *
              * In both cases we reset padding_idx to a safe value (0) to
              * prevent out-of-buffer reads.
              */
-            correct &= ( ssl->in_msglen >= padlen + 1 );
-            correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN +
+            correct &= ( padlen <= ssl->in_msglen );
+            correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN +
                                        ssl->transform_in->maclen );
 
             padding_idx *= correct;
 
-            for( i = 1; i <= 256; i++ )
+            for( i = 0; i < 256; i++ )
             {
-                real_count &= ( i <= padlen );
+                real_count &= ( i < padlen );
                 pad_count += real_count *
                              ( ssl->in_msg[padding_idx + i] == padlen - 1 );
             }
@@ -1951,8 +2052,10 @@
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
     }
 
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
     MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption",
                    ssl->in_msg, ssl->in_msglen );
+#endif
 
     /*
      * Authenticate if not done yet.
@@ -1985,20 +2088,69 @@
         {
             /*
              * Process MAC and always update for padlen afterwards to make
-             * total time independent of padlen
-             *
-             * extra_run compensates MAC check for padlen
+             * total time independent of padlen.
              *
              * Known timing attacks:
              *  - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
              *
-             * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values
-             * correctly. (We round down instead of up, so -56 is the correct
-             * value for our calculations instead of -55)
+             * To compensate for different timings for the MAC calculation
+             * depending on how much padding was removed (which is determined
+             * by padlen), process extra_run more blocks through the hash
+             * function.
+             *
+             * The formula in the paper is
+             *   extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 )
+             * where L1 is the size of the header plus the decrypted message
+             * plus CBC padding and L2 is the size of the header plus the
+             * decrypted message. This is for an underlying hash function
+             * with 64-byte blocks.
+             * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values
+             * correctly. We round down instead of up, so -56 is the correct
+             * value for our calculations instead of -55.
+             *
+             * Repeat the formula rather than defining a block_size variable.
+             * This avoids requiring division by a variable at runtime
+             * (which would be marginally less efficient and would require
+             * linking an extra division function in some builds).
              */
             size_t j, extra_run = 0;
-            extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
-                        ( 13 + ssl->in_msglen          + 8 ) / 64;
+
+            /*
+             * The next two sizes are the minimum and maximum values of
+             * in_msglen over all padlen values.
+             *
+             * They're independent of padlen, since we previously did
+             * in_msglen -= padlen.
+             *
+             * Note that max_len + maclen is never more than the buffer
+             * length, as we previously did in_msglen -= maclen too.
+             */
+            const size_t max_len = ssl->in_msglen + padlen;
+            const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
+
+            switch( ssl->transform_in->ciphersuite_info->mac )
+            {
+#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \
+    defined(MBEDTLS_SHA256_C)
+                case MBEDTLS_MD_MD5:
+                case MBEDTLS_MD_SHA1:
+                case MBEDTLS_MD_SHA256:
+                    /* 8 bytes of message size, 64-byte compression blocks */
+                    extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
+                                ( 13 + ssl->in_msglen          + 8 ) / 64;
+                    break;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+                case MBEDTLS_MD_SHA384:
+                    /* 16 bytes of message size, 128-byte compression blocks */
+                    extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 -
+                                ( 13 + ssl->in_msglen          + 16 ) / 128;
+                    break;
+#endif
+                default:
+                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+                    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            }
 
             extra_run &= correct * 0xFF;
 
@@ -2007,12 +2159,25 @@
             mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 );
             mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg,
                              ssl->in_msglen );
+            /* Make sure we access everything even when padlen > 0. This
+             * makes the synchronisation requirements for just-in-time
+             * Prime+Probe attacks much tighter and hopefully impractical. */
+            ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen );
             mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect );
-            /* Call mbedtls_md_process at least once due to cache attacks */
+
+            /* Call mbedtls_md_process at least once due to cache attacks
+             * that observe whether md_process() was called of not */
             for( j = 0; j < extra_run + 1; j++ )
                 mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
 
             mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec );
+
+            /* Make sure we access all the memory that could contain the MAC,
+             * before we check it in the next code block. This makes the
+             * synchronisation requirements for just-in-time Prime+Probe
+             * attacks much tighter and hopefully impractical. */
+            ssl_read_memory( ssl->in_msg + min_len,
+                                 max_len - min_len + ssl->transform_in->maclen );
         }
         else
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@@ -2022,9 +2187,11 @@
             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
         }
 
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
         MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen );
         MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", ssl->in_msg + ssl->in_msglen,
                                ssl->transform_in->maclen );
+#endif
 
         if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect,
                                       ssl->transform_in->maclen ) != 0 )
@@ -2053,6 +2220,16 @@
 
     if( ssl->in_msglen == 0 )
     {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
+            && ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
+        {
+            /* TLS v1.2 explicitly disallows zero-length messages which are not application data */
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
+            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
         ssl->nb_zero++;
 
         /*
@@ -2077,6 +2254,7 @@
     else
 #endif
     {
+        unsigned char i;
         for( i = 8; i > ssl_ep_len( ssl ); i-- )
             if( ++ssl->in_ctr[i - 1] != 0 )
                 break;
@@ -2126,7 +2304,7 @@
     ssl->transform_out->ctx_deflate.next_in = msg_pre;
     ssl->transform_out->ctx_deflate.avail_in = len_pre;
     ssl->transform_out->ctx_deflate.next_out = msg_post;
-    ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN - bytes_written;
+    ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written;
 
     ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
     if( ret != Z_OK )
@@ -2135,7 +2313,7 @@
         return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
     }
 
-    ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN -
+    ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN -
                       ssl->transform_out->ctx_deflate.avail_out - bytes_written;
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
@@ -2173,7 +2351,7 @@
     ssl->transform_in->ctx_inflate.next_in = msg_pre;
     ssl->transform_in->ctx_inflate.avail_in = len_pre;
     ssl->transform_in->ctx_inflate.next_out = msg_post;
-    ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_BUFFER_LEN -
+    ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN -
                                                header_bytes;
 
     ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
@@ -2183,7 +2361,7 @@
         return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
     }
 
-    ssl->in_msglen = MBEDTLS_SSL_BUFFER_LEN -
+    ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN -
                      ssl->transform_in->ctx_inflate.avail_out - header_bytes;
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
@@ -2258,7 +2436,7 @@
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
 
-    if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
+    if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -2344,7 +2522,7 @@
         }
         else
         {
-            len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
+            len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
 
             if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
                 timeout = ssl->handshake->retransmit_timeout;
@@ -2798,12 +2976,12 @@
         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
         {
             /* Make room for the additional DTLS fields */
-            if( MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen < 8 )
+            if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
                               "size %u, maximum %u",
                                (unsigned) ( ssl->in_hslen - 4 ),
-                               (unsigned) ( MBEDTLS_SSL_MAX_CONTENT_LEN - 12 ) ) );
+                               (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
                 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
             }
 
@@ -3016,7 +3194,7 @@
         MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
                             msg_len ) );
 
-        if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN )
+        if( ssl->in_hslen > MBEDTLS_SSL_IN_CONTENT_LEN )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) );
             return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
@@ -3120,7 +3298,7 @@
         ssl->next_record_offset = new_remain - ssl->in_hdr;
         ssl->in_left = ssl->next_record_offset + remain_len;
 
-        if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN -
+        if( ssl->in_left > MBEDTLS_SSL_IN_BUFFER_LEN -
                            (size_t)( ssl->in_hdr - ssl->in_buf ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) );
@@ -3496,7 +3674,7 @@
             ssl->conf->p_cookie,
             ssl->cli_id, ssl->cli_id_len,
             ssl->in_buf, ssl->in_left,
-            ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len );
+            ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
 
     MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
 
@@ -3593,7 +3771,7 @@
     }
 
     /* Check length against the size of our buffer */
-    if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN
+    if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN
                          - (size_t)( ssl->in_msg - ssl->in_buf ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
@@ -3687,7 +3865,7 @@
     if( ssl->transform_in == NULL )
     {
         if( ssl->in_msglen < 1 ||
-            ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
+            ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3703,7 +3881,7 @@
 
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
         if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
-            ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
+            ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3716,7 +3894,7 @@
          */
         if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
             ssl->in_msglen > ssl->transform_in->minlen +
-                             MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
+                             MBEDTLS_SSL_IN_CONTENT_LEN + 256 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3764,7 +3942,7 @@
         MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
                        ssl->in_msg, ssl->in_msglen );
 
-        if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
+        if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -4096,6 +4274,16 @@
 
     if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
     {
+        if( ssl->in_msglen != 2 )
+        {
+            /* Note: Standard allows for more than one 2 byte alert
+               to be packed in a single message, but Mbed TLS doesn't
+               currently support this. */
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d",
+                           ssl->in_msglen ) );
+            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        }
+
         MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
                        ssl->in_msg[0], ssl->in_msg[1] ) );
 
@@ -4325,10 +4513,10 @@
     while( crt != NULL )
     {
         n = crt->raw.len;
-        if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i )
+        if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
-                           i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) );
+                           i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) );
             return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE );
         }
 
@@ -4528,6 +4716,12 @@
 
     while( i < ssl->in_hslen )
     {
+        if ( i + 3 > ssl->in_hslen ) {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate 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 );
+        }
         if( ssl->in_msg[i] != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
@@ -5662,17 +5856,23 @@
                        const mbedtls_ssl_config *conf )
 {
     int ret;
-    const size_t len = MBEDTLS_SSL_BUFFER_LEN;
 
     ssl->conf = conf;
 
     /*
      * Prepare base structures
      */
-    if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL ||
-        ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL )
+    ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN );
+    if( ssl->in_buf == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) );
+        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    }
+
+    ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN );
+    if( ssl->out_buf == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) );
         mbedtls_free( ssl->in_buf );
         ssl->in_buf = NULL;
         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
@@ -5773,9 +5973,9 @@
     ssl->transform_in = NULL;
     ssl->transform_out = NULL;
 
-    memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
+    memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN );
     if( partial == 0 )
-        memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
+        memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN );
 
 #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
     if( mbedtls_ssl_hw_record_reset != NULL )
@@ -5995,27 +6195,27 @@
                                 mbedtls_x509_crt *cert,
                                 mbedtls_pk_context *key )
 {
-    mbedtls_ssl_key_cert *new;
+    mbedtls_ssl_key_cert *new_cert;
 
-    new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) );
-    if( new == NULL )
+    new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) );
+    if( new_cert == NULL )
         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
 
-    new->cert = cert;
-    new->key  = key;
-    new->next = NULL;
+    new_cert->cert = cert;
+    new_cert->key  = key;
+    new_cert->next = NULL;
 
     /* Update head is the list was null, else add to the end */
     if( *head == NULL )
     {
-        *head = new;
+        *head = new_cert;
     }
     else
     {
         mbedtls_ssl_key_cert *cur = *head;
         while( cur->next != NULL )
             cur = cur->next;
-        cur->next = new;
+        cur->next = new_cert;
     }
 
     return( 0 );
@@ -6100,7 +6300,7 @@
 
     /* Identity len will be encoded on two bytes */
     if( ( psk_identity_len >> 16 ) != 0 ||
-        psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
+        psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
     {
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
@@ -6401,7 +6601,7 @@
 int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code )
 {
     if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ||
-        mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN )
+        ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN )
     {
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
@@ -6679,15 +6879,15 @@
     /*
      * Assume mfl_code is correct since it was checked when set
      */
-    max_len = mfl_code_to_length[ssl->conf->mfl_code];
+    max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code );
 
     /*
      * Check if a smaller max length was negotiated
      */
     if( ssl->session_out != NULL &&
-        mfl_code_to_length[ssl->session_out->mfl_code] < max_len )
+        ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len )
     {
-        max_len = mfl_code_to_length[ssl->session_out->mfl_code];
+        max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code );
     }
 
     return max_len;
@@ -7231,8 +7431,16 @@
 }
 
 /*
- * Send application data to be encrypted by the SSL layer,
- * taking care of max fragment length and buffer size
+ * Send application data to be encrypted by the SSL layer, taking care of max
+ * fragment length and buffer size.
+ *
+ * According to RFC 5246 Section 6.2.1:
+ *
+ *      Zero-length fragments of Application data MAY be sent as they are
+ *      potentially useful as a traffic analysis countermeasure.
+ *
+ * Therefore, it is possible that the input message length is 0 and the
+ * corresponding return code is 0 on success.
  */
 static int ssl_write_real( mbedtls_ssl_context *ssl,
                            const unsigned char *buf, size_t len )
@@ -7241,7 +7449,7 @@
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
     size_t max_len = mbedtls_ssl_get_max_frag_len( ssl );
 #else
-    size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN;
+    size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
     if( len > max_len )
     {
@@ -7260,6 +7468,12 @@
 
     if( ssl->out_left != 0 )
     {
+        /*
+         * The user has previously tried to send the data and
+         * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
+         * written. In this case, we expect the high-level write function
+         * (e.g. mbedtls_ssl_write()) to be called with the same parameters
+         */
         if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
@@ -7268,6 +7482,11 @@
     }
     else
     {
+        /*
+         * The user is trying to send a message the first time, so we need to
+         * copy the data into the internal buffers and setup the data structure
+         * to keep track of partial writes
+         */
         ssl->out_msglen  = len;
         ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
         memcpy( ssl->out_msg, buf, len );
@@ -7543,20 +7762,20 @@
 
     if( ssl->out_buf != NULL )
     {
-        mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN );
+        mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN );
         mbedtls_free( ssl->out_buf );
     }
 
     if( ssl->in_buf != NULL )
     {
-        mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN );
+        mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN );
         mbedtls_free( ssl->in_buf );
     }
 
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     if( ssl->compress_buf != NULL )
     {
-        mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN );
+        mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
         mbedtls_free( ssl->compress_buf );
     }
 #endif
diff --git a/library/threading.c b/library/threading.c
index f1c3724..7a32e67 100644
--- a/library/threading.c
+++ b/library/threading.c
@@ -114,9 +114,6 @@
 #if defined(MBEDTLS_FS_IO)
     mbedtls_mutex_init( &mbedtls_threading_readdir_mutex );
 #endif
-#if defined(MBEDTLS_HAVE_TIME_DATE)
-    mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex );
-#endif
 }
 
 /*
@@ -127,9 +124,6 @@
 #if defined(MBEDTLS_FS_IO)
     mbedtls_mutex_free( &mbedtls_threading_readdir_mutex );
 #endif
-#if defined(MBEDTLS_HAVE_TIME_DATE)
-    mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex );
-#endif
 }
 #endif /* MBEDTLS_THREADING_ALT */
 
@@ -142,8 +136,5 @@
 #if defined(MBEDTLS_FS_IO)
 mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;
 #endif
-#if defined(MBEDTLS_HAVE_TIME_DATE)
-mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
-#endif
 
 #endif /* MBEDTLS_THREADING_C */
diff --git a/library/timing.c b/library/timing.c
index 6a30e51..3e8139f 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -39,7 +39,8 @@
 #if !defined(MBEDTLS_TIMING_ALT)
 
 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
-    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
+    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
+    !defined(__HAIKU__)
 #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h"
 #endif
 
diff --git a/library/version_features.c b/library/version_features.c
index bea2b13..777b603 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -39,6 +39,9 @@
 #if defined(MBEDTLS_NO_UDBL_DIVISION)
     "MBEDTLS_NO_UDBL_DIVISION",
 #endif /* MBEDTLS_NO_UDBL_DIVISION */
+#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
+    "MBEDTLS_NO_64BIT_MULTIPLICATION",
+#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */
 #if defined(MBEDTLS_HAVE_SSE2)
     "MBEDTLS_HAVE_SSE2",
 #endif /* MBEDTLS_HAVE_SSE2 */
@@ -102,6 +105,12 @@
 #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_CHACHAPOLY_ALT)
+    "MBEDTLS_CHACHAPOLY_ALT",
+#endif /* MBEDTLS_CHACHAPOLY_ALT */
 #if defined(MBEDTLS_CMAC_ALT)
     "MBEDTLS_CMAC_ALT",
 #endif /* MBEDTLS_CMAC_ALT */
@@ -117,6 +126,9 @@
 #if defined(MBEDTLS_GCM_ALT)
     "MBEDTLS_GCM_ALT",
 #endif /* MBEDTLS_GCM_ALT */
+#if defined(MBEDTLS_NIST_KW_ALT)
+    "MBEDTLS_NIST_KW_ALT",
+#endif /* MBEDTLS_NIST_KW_ALT */
 #if defined(MBEDTLS_MD2_ALT)
     "MBEDTLS_MD2_ALT",
 #endif /* MBEDTLS_MD2_ALT */
@@ -126,6 +138,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 */
@@ -552,6 +567,12 @@
 #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_CHACHAPOLY_C)
+    "MBEDTLS_CHACHAPOLY_C",
+#endif /* MBEDTLS_CHACHAPOLY_C */
 #if defined(MBEDTLS_CIPHER_C)
     "MBEDTLS_CIPHER_C",
 #endif /* MBEDTLS_CIPHER_C */
@@ -600,6 +621,9 @@
 #if defined(MBEDTLS_HMAC_DRBG_C)
     "MBEDTLS_HMAC_DRBG_C",
 #endif /* MBEDTLS_HMAC_DRBG_C */
+#if defined(MBEDTLS_NIST_KW_C)
+    "MBEDTLS_NIST_KW_C",
+#endif /* MBEDTLS_NIST_KW_C */
 #if defined(MBEDTLS_MD_C)
     "MBEDTLS_MD_C",
 #endif /* MBEDTLS_MD_C */
@@ -651,6 +675,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.c b/library/x509.c
index 371d6da..2e6795f 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -29,6 +29,10 @@
  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
  */
 
+/* Ensure gmtime_r is available even with -std=c99; must be included before
+ * config.h, which pulls in glibc's features.h. Harmless on other platforms. */
+#define _POSIX_C_SOURCE 200112L
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -59,26 +63,13 @@
 #define mbedtls_snprintf  snprintf
 #endif
 
-
 #if defined(MBEDTLS_HAVE_TIME)
 #include "mbedtls/platform_time.h"
 #endif
-
-#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
-#include <windows.h>
-#else
+#if defined(MBEDTLS_HAVE_TIME_DATE)
 #include <time.h>
 #endif
 
-#if defined(MBEDTLS_FS_IO)
-#include <stdio.h>
-#if !defined(_WIN32)
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#endif
-#endif
-
 #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
 #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
 
@@ -903,36 +894,18 @@
  * Set the time structure to the current time.
  * Return 0 on success, non-zero on failure.
  */
-#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
 static int x509_get_current_time( mbedtls_x509_time *now )
 {
-    SYSTEMTIME st;
-
-    GetSystemTime( &st );
-
-    now->year = st.wYear;
-    now->mon  = st.wMonth;
-    now->day  = st.wDay;
-    now->hour = st.wHour;
-    now->min  = st.wMinute;
-    now->sec  = st.wSecond;
-
-    return( 0 );
-}
-#else
-static int x509_get_current_time( mbedtls_x509_time *now )
-{
-    struct tm *lt;
+    struct tm *lt, tm_buf;
     mbedtls_time_t tt;
     int ret = 0;
 
-#if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
-#endif
-
     tt = mbedtls_time( NULL );
-    lt = gmtime( &tt );
+#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+    lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL;
+#else
+    lt = gmtime_r( &tt, &tm_buf );
+#endif
 
     if( lt == NULL )
         ret = -1;
@@ -946,14 +919,8 @@
         now->sec  = lt->tm_sec;
     }
 
-#if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
-#endif
-
     return( ret );
 }
-#endif /* _WIN32 && !EFIX64 && !EFI32 */
 
 /*
  * Return 0 if before <= after, 1 otherwise
diff --git a/library/x509_csr.c b/library/x509_csr.c
index 3e8e8fb..f844257 100644
--- a/library/x509_csr.c
+++ b/library/x509_csr.c
@@ -274,34 +274,25 @@
         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
 
 #if defined(MBEDTLS_PEM_PARSE_C)
-    mbedtls_pem_init( &pem );
-
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( buf[buflen - 1] != '\0' )
-        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-    else
+    if( buf[buflen - 1] == '\0' )
+    {
+        mbedtls_pem_init( &pem );
         ret = mbedtls_pem_read_buffer( &pem,
                                "-----BEGIN CERTIFICATE REQUEST-----",
                                "-----END CERTIFICATE REQUEST-----",
                                buf, NULL, 0, &use_len );
 
-    if( ret == 0 )
-    {
-        /*
-         * Was PEM encoded, parse the result
-         */
-        if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 )
-            return( ret );
+        if( ret == 0 )
+            /*
+             * Was PEM encoded, parse the result
+             */
+            ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen );
 
         mbedtls_pem_free( &pem );
-        return( 0 );
+        if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+            return( ret );
     }
-    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-    {
-        mbedtls_pem_free( &pem );
-        return( ret );
-    }
-    else
 #endif /* MBEDTLS_PEM_PARSE_C */
     return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) );
 }
diff --git a/programs/.gitignore b/programs/.gitignore
index ddfa1a4..0241896 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -45,6 +45,7 @@
 test/benchmark
 test/ecp-bench
 test/selftest
+test/cpp_dummy_build
 test/ssl_cert_test
 test/udp_proxy
 test/zeroize
diff --git a/programs/Makefile b/programs/Makefile
index 080e82d..b6d1fa2 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -4,9 +4,11 @@
 
 CFLAGS	?= -O2
 WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement
+WARNING_CXXFLAGS ?= -Wall -W
 LDFLAGS ?=
 
 LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../include -D_FILE_OFFSET_BITS=64
+LOCAL_CXXFLAGS = $(WARNING_CXXFLAGS) -I../include -D_FILE_OFFSET_BITS=64
 LOCAL_LDFLAGS = -L../library 			\
 		-lmbedtls$(SHARED_SUFFIX)	\
 		-lmbedx509$(SHARED_SUFFIX)	\
@@ -77,6 +79,10 @@
 APPS +=	ssl/ssl_pthread_server$(EXEXT)
 endif
 
+ifdef TEST_CPP
+APPS += test/cpp_dummy_build$(EXEXT)
+endif
+
 .SILENT:
 
 .PHONY: all clean list
@@ -242,6 +248,10 @@
 	echo "  CC    test/benchmark.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/benchmark.c   $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test/cpp_dummy_build$(EXEXT): test/cpp_dummy_build.cpp $(DEP)
+	echo "  CXX   test/cpp_dummy_build.cpp"
+	$(CXX) $(LOCAL_CXXFLAGS) $(CXXFLAGS) test/cpp_dummy_build.cpp   $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test/selftest$(EXEXT): test/selftest.c $(DEP)
 	echo "  CC    test/selftest.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/selftest.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/programs/aes/aescrypt2.c b/programs/aes/aescrypt2.c
index 4acf38d..69c4060 100644
--- a/programs/aes/aescrypt2.c
+++ b/programs/aes/aescrypt2.c
@@ -19,6 +19,11 @@
  *  This file is part of mbed TLS (https://tls.mbed.org)
  */
 
+/* Enable definition of fileno() even when compiling with -std=c99. Must be
+ * set before config.h, which pulls in glibc's features.h indirectly.
+ * Harmless on other platforms. */
+#define _POSIX_C_SOURCE 1
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -29,9 +34,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #include "mbedtls/aes.h"
 #include "mbedtls/md.h"
@@ -71,7 +79,8 @@
 #else
 int main( int argc, char *argv[] )
 {
-    int ret = 1;
+    int ret = 0;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
 
     unsigned int i, n;
     int mode, lastn;
@@ -429,7 +438,7 @@
         }
     }
 
-    ret = 0;
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
     if( fin )
@@ -452,6 +461,6 @@
     mbedtls_aes_free( &aes_ctx );
     mbedtls_md_free( &sha_ctx );
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_AES_C && MBEDTLS_SHA256_C && MBEDTLS_FS_IO */
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index 0e272eb..bc95eb9 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -20,6 +20,11 @@
  *  This file is part of mbed TLS (https://tls.mbed.org)
  */
 
+/* Enable definition of fileno() even when compiling with -std=c99. Must be
+ * set before config.h, which pulls in glibc's features.h indirectly.
+ * Harmless on other platforms. */
+#define _POSIX_C_SOURCE 1
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -30,9 +35,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_MD_C) && \
  defined(MBEDTLS_FS_IO)
@@ -74,6 +82,7 @@
 int main( int argc, char *argv[] )
 {
     int ret = 1, i, n;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     int mode;
     size_t keylen, ilen, olen;
     FILE *fkey, *fin = NULL, *fout = NULL;
@@ -526,7 +535,7 @@
         }
     }
 
-    ret = 0;
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
     if( fin )
@@ -549,6 +558,6 @@
     mbedtls_cipher_free( &cipher_ctx );
     mbedtls_md_free( &md_ctx );
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_CIPHER_C && MBEDTLS_MD_C && MBEDTLS_FS_IO */
diff --git a/programs/hash/generic_sum.c b/programs/hash/generic_sum.c
index d1e81d4..bbe8d92 100644
--- a/programs/hash/generic_sum.c
+++ b/programs/hash/generic_sum.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_MD_C) && defined(MBEDTLS_FS_IO)
 #include "mbedtls/md.h"
@@ -169,7 +172,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret, i;
+    int ret = 1, i;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     const mbedtls_md_info_t *md_info;
     mbedtls_md_context_t md_ctx;
 
@@ -196,7 +200,7 @@
         fflush( stdout ); getchar();
 #endif
 
-        return( 1 );
+        return( exit_code );
     }
 
     /*
@@ -206,12 +210,12 @@
     if( md_info == NULL )
     {
         mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[1] );
-        return( 1 );
+        return( exit_code );
     }
     if( mbedtls_md_setup( &md_ctx, md_info, 0 ) )
     {
         mbedtls_fprintf( stderr, "Failed to initialize context.\n" );
-        return( 1 );
+        return( exit_code );
     }
 
     ret = 0;
@@ -224,9 +228,12 @@
     for( i = 2; i < argc; i++ )
         ret |= generic_print( md_info, argv[i] );
 
+    if ( ret == 0 )
+        exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_md_free( &md_ctx );
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_MD_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index 0978408..3dadf48 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#define mbedtls_time_t     time_t
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define mbedtls_time_t          time_t
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
@@ -71,7 +74,8 @@
 {
     FILE *f;
 
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t n, buflen;
     mbedtls_net_context server_fd;
 
@@ -115,7 +119,6 @@
 
     if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not open rsa_pub.txt\n" \
                 "  ! Please run rsa_genkey first\n\n" );
         goto exit;
@@ -191,7 +194,6 @@
 
     if( dhm.len < 64 || dhm.len > 512 )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Invalid DHM modulus size\n\n" );
         goto exit;
     }
@@ -207,7 +209,6 @@
 
     if( ( n = (size_t) ( end - p ) ) != rsa.len )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Invalid RSA signature size\n\n" );
         goto exit;
     }
@@ -286,6 +287,8 @@
     buf[16] = '\0';
     mbedtls_printf( "\n  . Plaintext is \"%s\"\n\n", (char *) buf );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
     mbedtls_net_free( &server_fd );
@@ -301,7 +304,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
diff --git a/programs/pkey/dh_genprime.c b/programs/pkey/dh_genprime.c
index 84a94a1..dbe9153 100644
--- a/programs/pkey/dh_genprime.c
+++ b/programs/pkey/dh_genprime.c
@@ -30,9 +30,11 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
-#define mbedtls_printf     printf
-#define mbedtls_time_t     time_t
-#endif
+#define mbedtls_printf          printf
+#define mbedtls_time_t          time_t
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||   \
     !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) ||     \
@@ -69,6 +71,7 @@
 int main( int argc, char **argv )
 {
     int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_mpi G, P, Q;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
@@ -86,7 +89,7 @@
     {
     usage:
         mbedtls_printf( USAGE );
-        return( 1 );
+        return( exit_code );
     }
 
     for( i = 1; i < argc; i++ )
@@ -164,7 +167,6 @@
 
     if( ( fout = fopen( "dh_prime.txt", "wb+" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not create dh_prime.txt\n\n" );
         goto exit;
     }
@@ -180,6 +182,8 @@
     mbedtls_printf( " ok\n\n" );
     fclose( fout );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
     mbedtls_mpi_free( &G ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
@@ -191,7 +195,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_FS_IO &&
           MBEDTLS_CTR_DRBG_C && MBEDTLS_GENPRIME */
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index 4304231..c4e2c39 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#define mbedtls_time_t     time_t
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define mbedtls_time_t          time_t
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
@@ -71,7 +74,8 @@
 {
     FILE *f;
 
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t n, buflen;
     mbedtls_net_context listen_fd, client_fd;
 
@@ -121,7 +125,6 @@
 
     if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not open rsa_priv.txt\n" \
                 "  ! Please run rsa_genkey first\n\n" );
         goto exit;
@@ -164,7 +167,6 @@
 
     if( ( f = fopen( "dh_prime.txt", "rb" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not open dh_prime.txt\n" \
                 "  ! Please run dh_genprime first\n\n" );
         goto exit;
@@ -304,6 +306,8 @@
 
     mbedtls_printf( "\n\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
     mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
@@ -323,7 +327,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
diff --git a/programs/pkey/ecdh_curve25519.c b/programs/pkey/ecdh_curve25519.c
index e7ead9a..5db0408 100644
--- a/programs/pkey/ecdh_curve25519.c
+++ b/programs/pkey/ecdh_curve25519.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_ECDH_C) || \
     !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
@@ -51,7 +54,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_ecdh_context ctx_cli, ctx_srv;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
@@ -218,6 +222,7 @@
 
     mbedtls_printf( " ok\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
 
@@ -231,7 +236,7 @@
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
-    return( ret != 0 );
+    return( exit_code );
 }
 #endif /* MBEDTLS_ECDH_C && MBEDTLS_ECP_DP_CURVE25519_ENABLED &&
           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/ecdsa.c b/programs/pkey/ecdsa.c
index b474060..c653df9 100644
--- a/programs/pkey/ecdsa.c
+++ b/programs/pkey/ecdsa.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_ECDSA_C) && \
     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
@@ -98,7 +101,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_ecdsa_context ctx_sign, ctx_verify;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
@@ -115,7 +119,6 @@
 
     memset( sig, 0, sizeof( sig ) );
     memset( message, 0x25, sizeof( message ) );
-    ret = 1;
 
     if( argc != 1 )
     {
@@ -213,8 +216,6 @@
         goto exit;
     }
 
-    ret = 0;
-
     /*
      * Verify signature
      */
@@ -231,6 +232,8 @@
 
     mbedtls_printf( " ok\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
 #if defined(_WIN32)
@@ -243,7 +246,7 @@
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
           ECPARAMS */
diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c
index a7f5c90..f01bf5f 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO) && \
     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
@@ -186,7 +189,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_pk_context key;
     char buf[1024];
     int i;
@@ -214,7 +218,6 @@
     if( argc == 0 )
     {
     usage:
-        ret = 1;
         mbedtls_printf( USAGE );
 #if defined(MBEDTLS_ECP_C)
         mbedtls_printf( " available ec_curve values:\n" );
@@ -222,7 +225,7 @@
         mbedtls_printf( "    %s (default)\n", curve_info->name );
         while( ( ++curve_info )->name != NULL )
             mbedtls_printf( "    %s\n", curve_info->name );
-#endif
+#endif /* MBEDTLS_ECP_C */
         goto exit;
     }
 
@@ -411,9 +414,11 @@
 
     mbedtls_printf( " ok\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
-    if( ret != 0 && ret != 1)
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
 #ifdef MBEDTLS_ERROR_C
         mbedtls_strerror( ret, buf, sizeof( buf ) );
@@ -436,7 +441,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_PEM_WRITE_C && MBEDTLS_FS_IO &&
         * MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/key_app.c b/programs/pkey/key_app.c
index f1b548d..027b95f 100644
--- a/programs/pkey/key_app.c
+++ b/programs/pkey/key_app.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_BIGNUM_C) && \
     defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO)
@@ -83,7 +86,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     char buf[1024];
     int i;
     char *p, *q;
@@ -105,7 +109,7 @@
     {
     usage:
         mbedtls_printf( USAGE );
-        goto exit;
+        goto cleanup;
     }
 
     opt.mode                = DFL_MODE;
@@ -155,13 +159,13 @@
             if( ( f = fopen( opt.password_file, "rb" ) ) == NULL )
             {
                 mbedtls_printf( " failed\n  !  fopen returned NULL\n" );
-                goto exit;
+                goto cleanup;
             }
             if( fgets( buf, sizeof(buf), f ) == NULL )
             {
                 fclose( f );
                 mbedtls_printf( "Error: fgets() failed to retrieve password\n" );
-                goto exit;
+                goto cleanup;
             }
             fclose( f );
 
@@ -182,7 +186,7 @@
         if( ret != 0 )
         {
             mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret );
-            goto exit;
+            goto cleanup;
         }
 
         mbedtls_printf( " ok\n" );
@@ -200,17 +204,17 @@
                 ( ret = mbedtls_rsa_export_crt( rsa, &DP, &DQ, &QP ) )      != 0 )
             {
                 mbedtls_printf( " failed\n  ! could not export RSA parameters\n\n" );
-                goto exit;
+                goto cleanup;
             }
 
-            mbedtls_mpi_write_file( "N:  ",  &N,  16, NULL );
-            mbedtls_mpi_write_file( "E:  ",  &E,  16, NULL );
-            mbedtls_mpi_write_file( "D:  ",  &D,  16, NULL );
-            mbedtls_mpi_write_file( "P:  ",  &P,  16, NULL );
-            mbedtls_mpi_write_file( "Q:  ",  &Q,  16, NULL );
-            mbedtls_mpi_write_file( "DP: ",  &DP, 16, NULL );
-            mbedtls_mpi_write_file( "DQ:  ", &DQ, 16, NULL );
-            mbedtls_mpi_write_file( "QP:  ", &QP, 16, NULL );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "N:  ", &N, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "E:  ", &E, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "D:  ", &D, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "P:  ", &P, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q:  ", &Q, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "DP: ", &DP, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "DQ:  ", &DQ, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "QP:  ", &QP, 16, NULL ) );
         }
         else
 #endif
@@ -218,16 +222,16 @@
         if( mbedtls_pk_get_type( &pk ) == MBEDTLS_PK_ECKEY )
         {
             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( pk );
-            mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL );
-            mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL );
-            mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL );
-            mbedtls_mpi_write_file( "D   : ", &ecp->d  , 16, NULL );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "D   : ", &ecp->d  , 16, NULL ) );
         }
         else
 #endif
         {
             mbedtls_printf("Do not know how to print key information for this type\n" );
-            goto exit;
+            goto cleanup;
         }
     }
     else if( opt.mode == MODE_PUBLIC )
@@ -243,7 +247,7 @@
         if( ret != 0 )
         {
             mbedtls_printf( " failed\n  !  mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret );
-            goto exit;
+            goto cleanup;
         }
 
         mbedtls_printf( " ok\n" );
@@ -258,10 +262,10 @@
                                             NULL, &E ) ) != 0 )
             {
                 mbedtls_printf( " failed\n  ! could not export RSA parameters\n\n" );
-                goto exit;
+                goto cleanup;
             }
-            mbedtls_mpi_write_file( "N: ", &N, 16, NULL );
-            mbedtls_mpi_write_file( "E: ", &E, 16, NULL );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "N:  ", &N, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "E:  ", &E, 16, NULL ) );
         }
         else
 #endif
@@ -269,26 +273,28 @@
         if( mbedtls_pk_get_type( &pk ) == MBEDTLS_PK_ECKEY )
         {
             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( pk );
-            mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL );
-            mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL );
-            mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ) );
         }
         else
 #endif
         {
             mbedtls_printf("Do not know how to print key information for this type\n" );
-            goto exit;
+            goto cleanup;
         }
     }
     else
         goto usage;
 
-exit:
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
+cleanup:
 
 #if defined(MBEDTLS_ERROR_C)
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
-        mbedtls_strerror( ret, buf, sizeof(buf) );
+        mbedtls_strerror( ret, buf, sizeof( buf ) );
         mbedtls_printf( "  !  Last error was: %s\n", buf );
     }
 #endif
@@ -303,6 +309,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c
index 52b0f8e..13602c2 100644
--- a/programs/pkey/key_app_writer.c
+++ b/programs/pkey/key_app_writer.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_FS_IO)
 #include "mbedtls/error.h"
@@ -128,7 +131,7 @@
             return( ret );
 
         len = ret;
-        c = output_buf + sizeof(output_buf) - len - 1;
+        c = output_buf + sizeof(output_buf) - len;
     }
 
     if( ( f = fopen( output_file, "w" ) ) == NULL )
@@ -189,7 +192,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     char buf[1024];
     int i;
     char *p, *q;
@@ -210,7 +214,6 @@
     if( argc == 0 )
     {
     usage:
-        ret = 1;
         mbedtls_printf( USAGE );
         goto exit;
     }
@@ -403,9 +406,11 @@
         write_private_key( &key, opt.output_file );
     }
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
-    if( ret != 0 && ret != 1)
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
 #ifdef MBEDTLS_ERROR_C
         mbedtls_strerror( ret, buf, sizeof( buf ) );
@@ -426,6 +431,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/mpi_demo.c b/programs/pkey/mpi_demo.c
index afe8957..365bdc4 100644
--- a/programs/pkey/mpi_demo.c
+++ b/programs/pkey/mpi_demo.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_FS_IO)
 #include "mbedtls/bignum.h"
@@ -47,7 +50,8 @@
 #else
 int main( void )
 {
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_mpi E, P, Q, N, H, D, X, Y, Z;
 
     mbedtls_mpi_init( &E ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &N );
@@ -88,15 +92,16 @@
     MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( "  Z (decrypted)  = Y^D mod N = ", &Z, 10, NULL ) );
     mbedtls_printf( "\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 cleanup:
     mbedtls_mpi_free( &E ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); mbedtls_mpi_free( &N );
     mbedtls_mpi_free( &H ); mbedtls_mpi_free( &D ); mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
     mbedtls_mpi_free( &Z );
 
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
         mbedtls_printf( "\nAn error occurred.\n" );
-        ret = 1;
     }
 
 #if defined(_WIN32)
@@ -104,6 +109,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/pk_decrypt.c b/programs/pkey/pk_decrypt.c
index 32fbc75..00bd71e 100644
--- a/programs/pkey/pk_decrypt.c
+++ b/programs/pkey/pk_decrypt.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_PK_PARSE_C) && \
     defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_C) && \
@@ -59,7 +62,8 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int ret, c;
+    int ret = 1, c;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i, olen = 0;
     mbedtls_pk_context pk;
     mbedtls_entropy_context entropy;
@@ -71,7 +75,6 @@
 
     mbedtls_ctr_drbg_init( &ctr_drbg );
     memset(result, 0, sizeof( result ) );
-    ret = 1;
 
     if( argc != 2 )
     {
@@ -110,8 +113,6 @@
     /*
      * Extract the RSA encrypted value from the text file
      */
-    ret = 1;
-
     if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL )
     {
         mbedtls_printf( "\n  ! Could not open %s\n\n", "result-enc.txt" );
@@ -143,14 +144,14 @@
 
     mbedtls_printf( "The decrypted result is: '%s'\n\n", result );
 
-    ret = 0;
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
 #if defined(MBEDTLS_ERROR_C)
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
         mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
         mbedtls_printf( "  !  Last error was: %s\n", buf );
@@ -162,7 +163,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/pk_encrypt.c b/programs/pkey/pk_encrypt.c
index 7ca9d5a..400619c 100644
--- a/programs/pkey/pk_encrypt.c
+++ b/programs/pkey/pk_encrypt.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_PK_PARSE_C) && \
     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO) && \
@@ -59,7 +62,8 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i, olen = 0;
     mbedtls_pk_context pk;
     mbedtls_entropy_context entropy;
@@ -68,7 +72,6 @@
     unsigned char buf[512];
     const char *pers = "mbedtls_pk_encrypt";
 
-    ret = 1;
     mbedtls_ctr_drbg_init( &ctr_drbg );
 
     if( argc != 3 )
@@ -132,7 +135,6 @@
      */
     if( ( f = fopen( "result-enc.txt", "wb+" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not create %s\n\n", "result-enc.txt" );
         goto exit;
     }
@@ -145,12 +147,14 @@
 
     mbedtls_printf( "\n  . Done (created \"%s\")\n\n", "result-enc.txt" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
 #if defined(MBEDTLS_ERROR_C)
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
         mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
         mbedtls_printf( "  !  Last error was: %s\n", buf );
@@ -162,7 +166,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_PK_PARSE_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c
index 55df95e..7ec4675 100644
--- a/programs/pkey/pk_sign.c
+++ b/programs/pkey/pk_sign.c
@@ -30,9 +30,11 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
-#define mbedtls_snprintf   snprintf
-#define mbedtls_printf     printf
-#endif
+#define mbedtls_snprintf        snprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
     !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \
@@ -61,6 +63,7 @@
 {
     FILE *f;
     int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_pk_context pk;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
@@ -134,14 +137,12 @@
 
     if( ( f = fopen( filename, "wb+" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not create %s\n\n", filename );
         goto exit;
     }
 
     if( fwrite( buf, 1, olen, f ) != olen )
     {
-        ret = 1;
         mbedtls_printf( "failed\n  ! fwrite failed\n\n" );
         fclose( f );
         goto exit;
@@ -151,13 +152,15 @@
 
     mbedtls_printf( "\n  . Done (created \"%s\")\n\n", filename );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_pk_free( &pk );
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
 #if defined(MBEDTLS_ERROR_C)
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
         mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
         mbedtls_printf( "  !  Last error was: %s\n", buf );
@@ -169,7 +172,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret ? EXIT_FAILURE : EXIT_SUCCESS );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
diff --git a/programs/pkey/pk_verify.c b/programs/pkey/pk_verify.c
index d35d17f..3c7709f 100644
--- a/programs/pkey/pk_verify.c
+++ b/programs/pkey/pk_verify.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_snprintf   snprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_snprintf        snprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_MD_C) || \
     !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_PK_PARSE_C) ||   \
@@ -56,6 +59,7 @@
 {
     FILE *f;
     int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i;
     mbedtls_pk_context pk;
     unsigned char hash[32];
@@ -87,7 +91,6 @@
     /*
      * Extract the signature from the file
      */
-    ret = 1;
     mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[2] );
 
     if( ( f = fopen( filename, "rb" ) ) == NULL )
@@ -125,13 +128,13 @@
 
     mbedtls_printf( "\n  . OK (the signature is valid)\n\n" );
 
-    ret = 0;
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
     mbedtls_pk_free( &pk );
 
 #if defined(MBEDTLS_ERROR_C)
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
         mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
         mbedtls_printf( "  !  Last error was: %s\n", buf );
@@ -143,7 +146,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_SHA256_C &&
           MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_decrypt.c b/programs/pkey/rsa_decrypt.c
index 2da3fbf..0a252d2 100644
--- a/programs/pkey/rsa_decrypt.c
+++ b/programs/pkey/rsa_decrypt.c
@@ -30,11 +30,11 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
-#define mbedtls_printf     printf
-#define mbedtls_exit       exit
+#define mbedtls_printf       printf
+#define mbedtls_exit         exit
 #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
 #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
-#endif
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_RSA_C) && \
     defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_C) && \
@@ -61,7 +61,9 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int return_val, exit_val, c;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
+    int c;
     size_t i;
     mbedtls_rsa_context rsa;
     mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
@@ -73,7 +75,6 @@
     ((void) argv);
 
     memset(result, 0, sizeof( result ) );
-    exit_val = MBEDTLS_EXIT_SUCCESS;
 
     if( argc != 1 )
     {
@@ -83,7 +84,7 @@
         mbedtls_printf( "\n" );
 #endif
 
-        mbedtls_exit( MBEDTLS_EXIT_FAILURE );
+        mbedtls_exit( exit_code );
     }
 
     mbedtls_printf( "\n  . Seeding the random number generator..." );
@@ -96,14 +97,13 @@
     mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP );
     mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP );
 
-    return_val = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
+    ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
                                         &entropy, (const unsigned char *) pers,
                                         strlen( pers ) );
-    if( return_val != 0 )
+    if( ret != 0 )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n",
-                        return_val );
+                        ret );
         goto exit;
     }
 
@@ -112,40 +112,38 @@
 
     if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! Could not open rsa_priv.txt\n" \
                 "  ! Please run rsa_genkey first\n\n" );
         goto exit;
     }
 
-    if( ( return_val = mbedtls_mpi_read_file( &N , 16, f ) )  != 0 ||
-        ( return_val = mbedtls_mpi_read_file( &E , 16, f ) )  != 0 ||
-        ( return_val = mbedtls_mpi_read_file( &D , 16, f ) )  != 0 ||
-        ( return_val = mbedtls_mpi_read_file( &P , 16, f ) )  != 0 ||
-        ( return_val = mbedtls_mpi_read_file( &Q , 16, f ) )  != 0 ||
-        ( return_val = mbedtls_mpi_read_file( &DP , 16, f ) ) != 0 ||
-        ( return_val = mbedtls_mpi_read_file( &DQ , 16, f ) ) != 0 ||
-        ( return_val = mbedtls_mpi_read_file( &QP , 16, f ) ) != 0 )
+    if( ( ret = mbedtls_mpi_read_file( &N , 16, f ) )  != 0 ||
+        ( ret = mbedtls_mpi_read_file( &E , 16, f ) )  != 0 ||
+        ( ret = mbedtls_mpi_read_file( &D , 16, f ) )  != 0 ||
+        ( ret = mbedtls_mpi_read_file( &P , 16, f ) )  != 0 ||
+        ( ret = mbedtls_mpi_read_file( &Q , 16, f ) )  != 0 ||
+        ( ret = mbedtls_mpi_read_file( &DP , 16, f ) ) != 0 ||
+        ( ret = mbedtls_mpi_read_file( &DQ , 16, f ) ) != 0 ||
+        ( ret = mbedtls_mpi_read_file( &QP , 16, f ) ) != 0 )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! mbedtls_mpi_read_file returned %d\n\n",
-                        return_val );
+                        ret );
         fclose( f );
         goto exit;
     }
     fclose( f );
 
-    if( ( return_val = mbedtls_rsa_import( &rsa, &N, &P, &Q, &D, &E ) ) != 0 )
+    if( ( ret = mbedtls_rsa_import( &rsa, &N, &P, &Q, &D, &E ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_rsa_import returned %d\n\n",
-                        return_val );
+                        ret );
         goto exit;
     }
 
-    if( ( return_val = mbedtls_rsa_complete( &rsa ) ) != 0 )
+    if( ( ret = mbedtls_rsa_complete( &rsa ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_rsa_complete returned %d\n\n",
-                        return_val );
+                        ret );
         goto exit;
     }
 
@@ -154,7 +152,6 @@
      */
     if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( "\n  ! Could not open %s\n\n", "result-enc.txt" );
         goto exit;
     }
@@ -169,7 +166,6 @@
 
     if( i != rsa.len )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( "\n  ! Invalid RSA signature format\n\n" );
         goto exit;
     }
@@ -180,14 +176,13 @@
     mbedtls_printf( "\n  . Decrypting the encrypted data" );
     fflush( stdout );
 
-    return_val = mbedtls_rsa_pkcs1_decrypt( &rsa, mbedtls_ctr_drbg_random,
+    ret = mbedtls_rsa_pkcs1_decrypt( &rsa, mbedtls_ctr_drbg_random,
                                             &ctr_drbg, MBEDTLS_RSA_PRIVATE, &i,
                                             buf, result, 1024 );
-    if( return_val != 0 )
+    if( ret != 0 )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! mbedtls_rsa_pkcs1_decrypt returned %d\n\n",
-                        return_val );
+                        ret );
         goto exit;
     }
 
@@ -195,6 +190,8 @@
 
     mbedtls_printf( "The decrypted result is: '%s'\n\n", result );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
@@ -208,6 +205,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_val );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_encrypt.c b/programs/pkey/rsa_encrypt.c
index 81c27d8..411657a 100644
--- a/programs/pkey/rsa_encrypt.c
+++ b/programs/pkey/rsa_encrypt.c
@@ -30,12 +30,12 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#define mbedtls_exit       exit
-#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
-#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
-#endif
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define mbedtls_exit            exit
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_RSA_C) && \
     defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO) && \
@@ -61,7 +61,8 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int return_val, exit_val;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i;
     mbedtls_rsa_context rsa;
     mbedtls_entropy_context entropy;
@@ -71,8 +72,6 @@
     const char *pers = "rsa_encrypt";
     mbedtls_mpi N, E;
 
-    exit_val = MBEDTLS_EXIT_SUCCESS;
-
     if( argc != 2 )
     {
         mbedtls_printf( "usage: rsa_encrypt <string of max 100 characters>\n" );
@@ -81,7 +80,7 @@
         mbedtls_printf( "\n" );
 #endif
 
-        mbedtls_exit( MBEDTLS_EXIT_FAILURE );
+        mbedtls_exit( exit_code );
     }
 
     mbedtls_printf( "\n  . Seeding the random number generator..." );
@@ -92,14 +91,13 @@
     mbedtls_ctr_drbg_init( &ctr_drbg );
     mbedtls_entropy_init( &entropy );
 
-    return_val = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
-                                        &entropy, (const unsigned char *) pers,
-                                        strlen( pers ) );
-    if( return_val != 0 )
+    ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
+                                 &entropy, (const unsigned char *) pers,
+                                 strlen( pers ) );
+    if( ret != 0 )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n",
-                        return_val );
+                        ret );
         goto exit;
     }
 
@@ -108,35 +106,30 @@
 
     if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! Could not open rsa_pub.txt\n" \
                 "  ! Please run rsa_genkey first\n\n" );
         goto exit;
     }
 
-    if( ( return_val = mbedtls_mpi_read_file( &N, 16, f ) ) != 0 ||
-        ( return_val = mbedtls_mpi_read_file( &E, 16, f ) ) != 0 )
+    if( ( ret = mbedtls_mpi_read_file( &N, 16, f ) ) != 0 ||
+        ( ret = mbedtls_mpi_read_file( &E, 16, f ) ) != 0 )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! mbedtls_mpi_read_file returned %d\n\n",
-                        return_val );
+                        ret );
         fclose( f );
         goto exit;
     }
     fclose( f );
 
-    if( ( return_val = mbedtls_rsa_import( &rsa, &N, NULL,
-                                           NULL, NULL, &E ) ) != 0 )
+    if( ( ret = mbedtls_rsa_import( &rsa, &N, NULL, NULL, NULL, &E ) ) != 0 )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! mbedtls_rsa_import returned %d\n\n",
-                        return_val );
+                        ret );
         goto exit;
     }
 
     if( strlen( argv[1] ) > 100 )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " Input data larger than 100 characters.\n\n" );
         goto exit;
     }
@@ -149,14 +142,13 @@
     mbedtls_printf( "\n  . Generating the RSA encrypted value" );
     fflush( stdout );
 
-    return_val = mbedtls_rsa_pkcs1_encrypt( &rsa, mbedtls_ctr_drbg_random,
-                                            &ctr_drbg, MBEDTLS_RSA_PUBLIC,
-                                            strlen( argv[1] ), input, buf );
-    if( return_val != 0 )
+    ret = mbedtls_rsa_pkcs1_encrypt( &rsa, mbedtls_ctr_drbg_random,
+                                     &ctr_drbg, MBEDTLS_RSA_PUBLIC,
+                                     strlen( argv[1] ), input, buf );
+    if( ret != 0 )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! mbedtls_rsa_pkcs1_encrypt returned %d\n\n",
-                        return_val );
+                        ret );
         goto exit;
     }
 
@@ -165,7 +157,6 @@
      */
     if( ( f = fopen( "result-enc.txt", "wb+" ) ) == NULL )
     {
-        exit_val = MBEDTLS_EXIT_FAILURE;
         mbedtls_printf( " failed\n  ! Could not create %s\n\n", "result-enc.txt" );
         goto exit;
     }
@@ -178,6 +169,8 @@
 
     mbedtls_printf( "\n  . Done (created \"%s\")\n\n", "result-enc.txt" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_mpi_free( &N ); mbedtls_mpi_free( &E );
     mbedtls_ctr_drbg_free( &ctr_drbg );
@@ -189,7 +182,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( exit_val );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/rsa_genkey.c b/programs/pkey/rsa_genkey.c
index 9399217..3359e14 100644
--- a/programs/pkey/rsa_genkey.c
+++ b/programs/pkey/rsa_genkey.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \
     defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) && \
@@ -61,7 +64,8 @@
 #else
 int main( void )
 {
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_rsa_context rsa;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
@@ -105,14 +109,12 @@
         ( ret = mbedtls_rsa_export_crt( &rsa, &DP, &DQ, &QP ) )      != 0 )
     {
         mbedtls_printf( " failed\n  ! could not export RSA parameters\n\n" );
-        ret = 1;
         goto exit;
     }
 
     if( ( fpub = fopen( "rsa_pub.txt", "wb+" ) ) == NULL )
     {
         mbedtls_printf( " failed\n  ! could not open rsa_pub.txt for writing\n\n" );
-        ret = 1;
         goto exit;
     }
 
@@ -129,7 +131,6 @@
     if( ( fpriv = fopen( "rsa_priv.txt", "wb+" ) ) == NULL )
     {
         mbedtls_printf( " failed\n  ! could not open rsa_priv.txt for writing\n" );
-        ret = 1;
         goto exit;
     }
 
@@ -160,6 +161,8 @@
 */
     mbedtls_printf( " ok\n\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
     if( fpub  != NULL )
@@ -180,7 +183,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_RSA_C &&
           MBEDTLS_GENPRIME && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c
index 89018cb..b16fe5d 100644
--- a/programs/pkey/rsa_sign.c
+++ b/programs/pkey/rsa_sign.c
@@ -29,10 +29,13 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#define mbedtls_snprintf   snprintf
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define mbedtls_snprintf        snprintf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) ||  \
     !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \
@@ -55,7 +58,8 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i;
     mbedtls_rsa_context rsa;
     unsigned char hash[32];
@@ -69,8 +73,6 @@
     mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP );
     mbedtls_mpi_init( &DQ ); mbedtls_mpi_init( &QP );
 
-    ret = 1;
-
     if( argc != 2 )
     {
         mbedtls_printf( "usage: rsa_sign <filename>\n" );
@@ -87,7 +89,6 @@
 
     if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not open rsa_priv.txt\n" \
                 "  ! Please run rsa_genkey first\n\n" );
         goto exit;
@@ -159,7 +160,6 @@
 
     if( ( f = fopen( filename, "wb+" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not create %s\n\n", argv[1] );
         goto exit;
     }
@@ -172,6 +172,8 @@
 
     mbedtls_printf( "\n  . Done (created \"%s\")\n\n", filename );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
     mbedtls_rsa_free( &rsa );
@@ -184,7 +186,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
           MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_sign_pss.c b/programs/pkey/rsa_sign_pss.c
index 7b6f14d..b0b0f7e 100644
--- a/programs/pkey/rsa_sign_pss.c
+++ b/programs/pkey/rsa_sign_pss.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_snprintf   snprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_snprintf        snprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
     !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) ||        \
@@ -61,6 +64,7 @@
 {
     FILE *f;
     int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_pk_context pk;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
@@ -101,7 +105,6 @@
 
     if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not read key from '%s'\n", argv[1] );
         mbedtls_printf( "  ! mbedtls_pk_parse_public_keyfile returned %d\n\n", ret );
         goto exit;
@@ -109,7 +112,6 @@
 
     if( !mbedtls_pk_can_do( &pk, MBEDTLS_PK_RSA ) )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Key is not an RSA key\n" );
         goto exit;
     }
@@ -145,7 +147,6 @@
 
     if( ( f = fopen( filename, "wb+" ) ) == NULL )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Could not create %s\n\n", filename );
         goto exit;
     }
@@ -161,6 +162,8 @@
 
     mbedtls_printf( "\n  . Done (created \"%s\")\n\n", filename );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_pk_free( &pk );
     mbedtls_ctr_drbg_free( &ctr_drbg );
@@ -171,7 +174,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_RSA_C &&
           MBEDTLS_SHA256_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c
index 1f827aa..6f88345 100644
--- a/programs/pkey/rsa_verify.c
+++ b/programs/pkey/rsa_verify.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#define mbedtls_snprintf   snprintf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define mbedtls_snprintf        snprintf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) ||  \
     !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) || \
@@ -54,7 +57,8 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int ret, c;
+    int ret = 1, c;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i;
     mbedtls_rsa_context rsa;
     unsigned char hash[32];
@@ -62,7 +66,6 @@
     char filename[512];
 
     mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
-    ret = 1;
 
     if( argc != 2 )
     {
@@ -100,7 +103,6 @@
     /*
      * Extract the RSA signature from the text file
      */
-    ret = 1;
     mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[1] );
 
     if( ( f = fopen( filename, "rb" ) ) == NULL )
@@ -146,7 +148,7 @@
 
     mbedtls_printf( "\n  . OK (the signature is valid)\n\n" );
 
-    ret = 0;
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
 
@@ -157,7 +159,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
           MBEDTLS_FS_IO */
diff --git a/programs/pkey/rsa_verify_pss.c b/programs/pkey/rsa_verify_pss.c
index 31b720f..7c9c68f 100644
--- a/programs/pkey/rsa_verify_pss.c
+++ b/programs/pkey/rsa_verify_pss.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_snprintf   snprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_snprintf        snprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
     !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) ||        \
@@ -60,6 +63,7 @@
 {
     FILE *f;
     int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     size_t i;
     mbedtls_pk_context pk;
     unsigned char hash[32];
@@ -91,7 +95,6 @@
 
     if( !mbedtls_pk_can_do( &pk, MBEDTLS_PK_RSA ) )
     {
-        ret = 1;
         mbedtls_printf( " failed\n  ! Key is not an RSA key\n" );
         goto exit;
     }
@@ -101,7 +104,6 @@
     /*
      * Extract the RSA signature from the file
      */
-    ret = 1;
     mbedtls_snprintf( filename, 512, "%s.sig", argv[2] );
 
     if( ( f = fopen( filename, "rb" ) ) == NULL )
@@ -139,7 +141,7 @@
 
     mbedtls_printf( "\n  . OK (the signature is valid)\n\n" );
 
-    ret = 0;
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 exit:
     mbedtls_pk_free( &pk );
@@ -149,7 +151,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
           MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO */
diff --git a/programs/random/gen_entropy.c b/programs/random/gen_entropy.c
index 792d381..a1eb386 100644
--- a/programs/random/gen_entropy.c
+++ b/programs/random/gen_entropy.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_FS_IO)
 #include "mbedtls/entropy.h"
@@ -49,20 +52,21 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int i, k, ret;
+    int i, k, ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_entropy_context entropy;
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
 
     if( argc < 2 )
     {
         mbedtls_fprintf( stderr, "usage: %s <output filename>\n", argv[0] );
-        return( 1 );
+        return( exit_code );
     }
 
     if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
     {
         mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] );
-        return( 1 );
+        return( exit_code );
     }
 
     mbedtls_entropy_init( &entropy );
@@ -72,7 +76,8 @@
         ret = mbedtls_entropy_func( &entropy, buf, sizeof( buf ) );
         if( ret != 0 )
         {
-            mbedtls_printf("failed!\n");
+            mbedtls_printf( "  failed\n  !  mbedtls_entropy_func returned -%04X\n",
+                            ret );
             goto cleanup;
         }
 
@@ -83,7 +88,7 @@
         fflush( stdout );
     }
 
-    ret = 0;
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 cleanup:
     mbedtls_printf( "\n" );
@@ -91,6 +96,6 @@
     fclose( f );
     mbedtls_entropy_free( &entropy );
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_ENTROPY_C */
diff --git a/programs/random/gen_random_ctr_drbg.c b/programs/random/gen_random_ctr_drbg.c
index c76f99d..5ade946 100644
--- a/programs/random/gen_random_ctr_drbg.c
+++ b/programs/random/gen_random_ctr_drbg.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_CTR_DRBG_C) && defined(MBEDTLS_ENTROPY_C) && \
  defined(MBEDTLS_FS_IO)
@@ -52,7 +55,8 @@
 int main( int argc, char *argv[] )
 {
     FILE *f;
-    int i, k, ret;
+    int i, k, ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_ctr_drbg_context ctr_drbg;
     mbedtls_entropy_context entropy;
     unsigned char buf[1024];
@@ -62,13 +66,13 @@
     if( argc < 2 )
     {
         mbedtls_fprintf( stderr, "usage: %s <output filename>\n", argv[0] );
-        return( 1 );
+        return( exit_code );
     }
 
     if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
     {
         mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] );
-        return( 1 );
+        return( exit_code );
     }
 
     mbedtls_entropy_init( &entropy );
@@ -116,7 +120,7 @@
         fflush( stdout );
     }
 
-    ret = 0;
+    exit_code = MBEDTLS_EXIT_SUCCESS;
 
 cleanup:
     mbedtls_printf("\n");
@@ -125,6 +129,6 @@
     mbedtls_ctr_drbg_free( &ctr_drbg );
     mbedtls_entropy_free( &entropy );
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_CTR_DRBG_C && MBEDTLS_ENTROPY_C */
diff --git a/programs/random/gen_random_havege.c b/programs/random/gen_random_havege.c
index 6c31462..3fb3f01 100644
--- a/programs/random/gen_random_havege.c
+++ b/programs/random/gen_random_havege.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_HAVEGE_C) && defined(MBEDTLS_FS_IO)
 #include "mbedtls/havege.h"
@@ -51,20 +54,21 @@
 {
     FILE *f;
     time_t t;
-    int i, k, ret = 0;
+    int i, k, ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_havege_state hs;
     unsigned char buf[1024];
 
     if( argc < 2 )
     {
         mbedtls_fprintf( stderr, "usage: %s <output filename>\n", argv[0] );
-        return( 1 );
+        return( exit_code );
     }
 
     if( ( f = fopen( argv[1], "wb+" ) ) == NULL )
     {
         mbedtls_printf( "failed to open '%s' for writing.\n", argv[1] );
-        return( 1 );
+        return( exit_code );
     }
 
     mbedtls_havege_init( &hs );
@@ -73,11 +77,10 @@
 
     for( i = 0, k = 768; i < k; i++ )
     {
-        if( mbedtls_havege_random( &hs, buf, sizeof( buf ) ) != 0 )
+        if( ( ret = mbedtls_havege_random( &hs, buf, sizeof( buf ) ) ) != 0 )
         {
-            mbedtls_printf( "Failed to get random from source.\n" );
-
-            ret = 1;
+            mbedtls_printf( " failed\n  !  mbedtls_havege_random returned -0x%04X",
+                            -ret );
             goto exit;
         }
 
@@ -93,9 +96,11 @@
 
     mbedtls_printf(" \n ");
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_havege_free( &hs );
     fclose( f );
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_HAVEGE_C */
diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c
index 01cee13..bf7c013 100644
--- a/programs/ssl/ssl_client1.c
+++ b/programs/ssl/ssl_client1.c
@@ -30,11 +30,13 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
-#define mbedtls_time       time
-#define mbedtls_time_t     time_t
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#define mbedtls_time            time
+#define mbedtls_time_t          time_t
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
     !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
@@ -80,7 +82,8 @@
 
 int main( void )
 {
-    int ret, len;
+    int ret = 1, len;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_net_context server_fd;
     uint32_t flags;
     unsigned char buf[1024];
@@ -281,10 +284,12 @@
 
     mbedtls_ssl_close_notify( &ssl );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
 #ifdef MBEDTLS_ERROR_C
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
         char error_buf[100];
         mbedtls_strerror( ret, error_buf, 100 );
@@ -305,7 +310,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 5d8969d..0dd9e3f 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -246,8 +246,12 @@
     "    server_addr=%%s      default: given by name\n"     \
     "    server_port=%%d      default: 4433\n"              \
     "    request_page=%%s     default: \".\"\n"             \
-    "    request_size=%%d     default: about 34 (basic request)\n" \
-    "                        (minimum: 0, max: " MAX_REQUEST_SIZE_STR " )\n" \
+    "    request_size=%%d     default: about 34 (basic request)\n"           \
+    "                        (minimum: 0, max: " MAX_REQUEST_SIZE_STR ")\n"  \
+    "                        If 0, in the first exchange only an empty\n"    \
+    "                        application data message is sent followed by\n" \
+    "                        a second non-empty message before attempting\n" \
+    "                        to read a response from the server\n"           \
     "    debug_level=%%d      default: 0 (disabled)\n"             \
     "    nbio=%%d             default: 0 (blocking I/O)\n"         \
     "                        options: 1 (non-blocking), 2 (added delays)\n"   \
@@ -1663,10 +1667,13 @@
 
     if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM )
     {
-        for( written = 0, frags = 0; written < len; written += ret, frags++ )
+        written = 0;
+        frags = 0;
+
+        do
         {
             while( ( ret = mbedtls_ssl_write( &ssl, buf + written,
-                                              len - written ) ) <= 0 )
+                                              len - written ) ) < 0 )
             {
                 if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
                     ret != MBEDTLS_ERR_SSL_WANT_WRITE )
@@ -1686,7 +1693,11 @@
 #endif
                 }
             }
+
+            frags++;
+            written += ret;
         }
+        while( written < len );
     }
     else /* Not stream, so datagram */
     {
@@ -1730,6 +1741,13 @@
     mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n",
                     written, frags, (char *) buf );
 
+    /* Send a non-empty request if request_size == 0 */
+    if ( len == 0 )
+    {
+        opt.request_size = DFL_REQUEST_SIZE;
+        goto send_request;
+    }
+
     /*
      * 7. Read the HTTP response
      */
diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c
index 7624896..1c3a806 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -29,10 +29,13 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#define mbedtls_time_t     time_t
-#endif
+#include <stdlib.h>
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define mbedtls_time_t          time_t
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_CERTS_C) ||    \
     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_SSL_TLS_C) || \
@@ -95,7 +98,8 @@
 
 int main( void )
 {
-    int ret, len, cnt = 0, pid;
+    int ret = 1, len, cnt = 0, pid;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_net_context listen_fd, client_fd;
     unsigned char buf[1024];
     const char *pers = "ssl_fork_server";
@@ -392,6 +396,8 @@
         goto exit;
     }
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_net_free( &client_fd );
     mbedtls_net_free( &listen_fd );
@@ -408,7 +414,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C &&
           MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C &&
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index 04b847a..d3b569c 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -19,6 +19,11 @@
  *  This file is part of mbed TLS (https://tls.mbed.org)
  */
 
+/* Enable definition of gethostname() even when compiling with -std=c99. Must
+ * be set before config.h, which pulls in glibc's features.h indirectly.
+ * Harmless on other platforms. */
+#define _POSIX_C_SOURCE 200112L
+
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/config.h"
 #else
@@ -30,11 +35,13 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
-#define mbedtls_time       time
-#define mbedtls_time_t     time_t
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#define mbedtls_time            time
+#define mbedtls_time_t          time_t
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
     !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
@@ -346,7 +353,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0, len;
+    int ret = 1, len;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_net_context server_fd;
     unsigned char buf[1024];
 #if defined(MBEDTLS_BASE64_C)
@@ -499,8 +507,8 @@
                               mbedtls_test_cas_pem_len );
 #else
     {
-        ret = 1;
         mbedtls_printf("MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C not defined.");
+        goto exit;
     }
 #endif
     if( ret < 0 )
@@ -529,8 +537,8 @@
                               mbedtls_test_cli_crt_len );
 #else
     {
-        ret = -1;
         mbedtls_printf("MBEDTLS_CERTS_C not defined.");
+        goto exit;
     }
 #endif
     if( ret != 0 )
@@ -549,8 +557,8 @@
                 mbedtls_test_cli_key_len, NULL, 0 );
 #else
     {
-        ret = -1;
         mbedtls_printf("MBEDTLS_CERTS_C or MBEDTLS_PEM_PARSE_C not defined.");
+        goto exit;
     }
 #endif
     if( ret != 0 )
@@ -819,6 +827,8 @@
 
     mbedtls_ssl_close_notify( &ssl );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
     mbedtls_net_free( &server_fd );
@@ -835,7 +845,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C **
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 3a413ad..7654a64 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -97,6 +97,10 @@
 #include <windows.h>
 #endif
 
+/* Size of memory to be allocated for the heap, when using the library's memory
+ * management and MBEDTLS_MEMORY_BUFFER_ALLOC_C is enabled. */
+#define MEMORY_HEAP_SIZE        120000
+
 #define DFL_SERVER_ADDR         NULL
 #define DFL_SERVER_PORT         "4433"
 #define DFL_DEBUG_LEVEL         0
@@ -1212,7 +1216,7 @@
     const char *alpn_list[ALPN_LIST_SIZE];
 #endif
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    unsigned char alloc_buf[100000];
+    unsigned char alloc_buf[MEMORY_HEAP_SIZE];
 #endif
 
     int i;
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index 0c5ce27..9ca0cb2 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -16,6 +16,11 @@
 add_executable(benchmark benchmark.c)
 target_link_libraries(benchmark ${libs})
 
+if(TEST_CPP)
+    add_executable(cpp_dummy_build cpp_dummy_build.cpp)
+    target_link_libraries(cpp_dummy_build ${libs})
+endif()
+
 add_executable(ssl_cert_test ssl_cert_test.c)
 target_link_libraries(ssl_cert_test ${libs})
 
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 89fdb84..5277ceb 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -61,9 +61,12 @@
 #include "mbedtls/aria.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"
@@ -98,9 +101,10 @@
 
 #define OPTIONS                                                         \
     "md4, md5, ripemd160, sha1, sha256, sha512,\n"                      \
-    "arc4, des3, des, camellia, blowfish,\n"                            \
-    "aes_cbc, aes_gcm, aes_ccm, aes_cmac, aes_xts,\n"                   \
-    "des3_cmac, havege, ctr_drbg, hmac_drbg,\n"                         \
+    "arc4, des3, des, camellia, blowfish, chacha20,\n"                  \
+    "aes_cbc, aes_gcm, aes_ccm, aes_ctx, chachapoly,\n"                 \
+    "aes_cmac, des3_cmac, poly1305\n"                                   \
+    "havege, ctr_drbg, hmac_drbg\n"                                     \
     "rsa, dhm, ecdsa, ecdh.\n"
 
 #if defined(MBEDTLS_ERROR_C)
@@ -115,25 +119,34 @@
 #define TIME_AND_TSC( TITLE, CODE )                                     \
 do {                                                                    \
     unsigned long ii, jj, tsc;                                          \
+    int ret = 0;                                                        \
                                                                         \
     mbedtls_printf( HEADER_FORMAT, TITLE );                             \
     fflush( stdout );                                                   \
                                                                         \
     mbedtls_set_alarm( 1 );                                             \
-    for( ii = 1; ! mbedtls_timing_alarmed; ii++ )                       \
+    for( ii = 1; ret == 0 && ! mbedtls_timing_alarmed; ii++ )           \
     {                                                                   \
-        CODE;                                                           \
+        ret = CODE;                                                     \
     }                                                                   \
                                                                         \
     tsc = mbedtls_timing_hardclock();                                   \
-    for( jj = 0; jj < 1024; jj++ )                                      \
+    for( jj = 0; ret == 0 && jj < 1024; jj++ )                          \
     {                                                                   \
-        CODE;                                                           \
+        ret = CODE;                                                     \
     }                                                                   \
                                                                         \
-    mbedtls_printf( "%9lu KiB/s,  %9lu cycles/byte\n",                   \
-                     ii * BUFSIZE / 1024,                               \
-                     ( mbedtls_timing_hardclock() - tsc ) / ( jj * BUFSIZE ) );         \
+    if( ret != 0 )                                                      \
+    {                                                                   \
+        PRINT_ERROR;                                                    \
+    }                                                                   \
+    else                                                                \
+    {                                                                   \
+        mbedtls_printf( "%9lu KiB/s,  %9lu cycles/byte\n",              \
+                         ii * BUFSIZE / 1024,                           \
+                         ( mbedtls_timing_hardclock() - tsc )           \
+                         / ( jj * BUFSIZE ) );                          \
+    }                                                                   \
 } while( 0 )
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_MEMORY_DEBUG)
@@ -233,8 +246,10 @@
 typedef struct {
     char md4, md5, ripemd160, sha1, sha256, sha512,
          arc4, des3, des,
-         aes_cbc, aes_gcm, aes_ccm, aes_cmac, aes_xts,
-         des3_cmac, aria, camellia, blowfish,
+         aes_cbc, aes_gcm, aes_ccm, aes_xts, chachapoly,
+         aes_cmac, des3_cmac,
+         aria, camellia, blowfish, chacha20,
+         poly1305,
          havege, ctr_drbg, hmac_drbg,
          rsa, dhm, ecdsa, ecdh;
 } todo_list;
@@ -285,6 +300,8 @@
                 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], "des3_cmac" ) == 0 )
@@ -295,6 +312,10 @@
                 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 )
@@ -497,6 +518,26 @@
         }
     }
 #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_encrypt_and_tag( &chachapoly,
+                    BUFSIZE, tmp, NULL, 0, buf, buf, tmp ) );
+
+        mbedtls_chachapoly_free( &chachapoly );
+    }
+#endif
 #if defined(MBEDTLS_CMAC_C)
     if( todo.aes_cmac )
     {
@@ -574,6 +615,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 )
     {
@@ -618,15 +673,13 @@
         if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
         TIME_AND_TSC( "CTR_DRBG (NOPR)",
-                if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
+                mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) );
 
         if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
         mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON );
         TIME_AND_TSC( "CTR_DRBG (PR)",
-                if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
+                mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) );
         mbedtls_ctr_drbg_free( &ctr_drbg );
     }
 #endif
@@ -646,8 +699,7 @@
         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
         TIME_AND_TSC( "HMAC_DRBG SHA-1 (NOPR)",
-                if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
+                mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) );
         mbedtls_hmac_drbg_free( &hmac_drbg );
 
         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
@@ -655,8 +707,7 @@
         mbedtls_hmac_drbg_set_prediction_resistance( &hmac_drbg,
                                              MBEDTLS_HMAC_DRBG_PR_ON );
         TIME_AND_TSC( "HMAC_DRBG SHA-1 (PR)",
-                if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
+                mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) );
         mbedtls_hmac_drbg_free( &hmac_drbg );
 #endif
 
@@ -667,8 +718,7 @@
         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
         TIME_AND_TSC( "HMAC_DRBG SHA-256 (NOPR)",
-                if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
+                mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) );
         mbedtls_hmac_drbg_free( &hmac_drbg );
 
         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
@@ -676,8 +726,7 @@
         mbedtls_hmac_drbg_set_prediction_resistance( &hmac_drbg,
                                              MBEDTLS_HMAC_DRBG_PR_ON );
         TIME_AND_TSC( "HMAC_DRBG SHA-256 (PR)",
-                if( mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) != 0 )
-                mbedtls_exit(1) );
+                mbedtls_hmac_drbg_random( &hmac_drbg, buf, BUFSIZE ) );
         mbedtls_hmac_drbg_free( &hmac_drbg );
 #endif
     }
diff --git a/programs/test/cpp_dummy_build.cpp b/programs/test/cpp_dummy_build.cpp
new file mode 100644
index 0000000..c652884
--- /dev/null
+++ b/programs/test/cpp_dummy_build.cpp
@@ -0,0 +1,119 @@
+/*
+ *  This program is a dummy C++ program to ensure Mbed TLS library header files
+ *  can be included and built with a C++ compiler.
+ *
+ *  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/aes.h"
+#include "mbedtls/aesni.h"
+#include "mbedtls/arc4.h"
+#include "mbedtls/aria.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/asn1write.h"
+#include "mbedtls/base64.h"
+#include "mbedtls/bignum.h"
+#include "mbedtls/blowfish.h"
+#include "mbedtls/bn_mul.h"
+#include "mbedtls/camellia.h"
+#include "mbedtls/ccm.h"
+#include "mbedtls/certs.h"
+#include "mbedtls/chacha20.h"
+#include "mbedtls/chachapoly.h"
+#include "mbedtls/check_config.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/cipher_internal.h"
+#include "mbedtls/cmac.h"
+#include "mbedtls/compat-1.3.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/des.h"
+#include "mbedtls/dhm.h"
+#include "mbedtls/ecdh.h"
+#include "mbedtls/ecdsa.h"
+#include "mbedtls/ecjpake.h"
+#include "mbedtls/ecp.h"
+#include "mbedtls/ecp_internal.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/entropy_poll.h"
+#include "mbedtls/error.h"
+#include "mbedtls/gcm.h"
+#include "mbedtls/havege.h"
+#include "mbedtls/hkdf.h"
+#include "mbedtls/hmac_drbg.h"
+#include "mbedtls/md.h"
+#include "mbedtls/md2.h"
+#include "mbedtls/md4.h"
+#include "mbedtls/md5.h"
+#include "mbedtls/md_internal.h"
+#include "mbedtls/net.h"
+#include "mbedtls/net_sockets.h"
+#include "mbedtls/nist_kw.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/padlock.h"
+#include "mbedtls/pem.h"
+#include "mbedtls/pk.h"
+#include "mbedtls/pk_internal.h"
+#include "mbedtls/pkcs11.h"
+#include "mbedtls/pkcs12.h"
+#include "mbedtls/pkcs5.h"
+#include "mbedtls/platform_time.h"
+#include "mbedtls/platform_util.h"
+#include "mbedtls/poly1305.h"
+#include "mbedtls/ripemd160.h"
+#include "mbedtls/rsa.h"
+#include "mbedtls/rsa_internal.h"
+#include "mbedtls/sha1.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/sha512.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/ssl_cache.h"
+#include "mbedtls/ssl_ciphersuites.h"
+#include "mbedtls/ssl_cookie.h"
+#include "mbedtls/ssl_internal.h"
+#include "mbedtls/ssl_ticket.h"
+#include "mbedtls/threading.h"
+#include "mbedtls/timing.h"
+#include "mbedtls/version.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/x509_crl.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_csr.h"
+#include "mbedtls/xtea.h"
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#endif
+
+#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
+#include "mbedtls/memory_buffer_alloc.h"
+#endif
+
+int main()
+{
+    mbedtls_platform_context *ctx = NULL;
+    mbedtls_platform_setup(ctx);
+    mbedtls_printf("CPP Build test\n");
+    mbedtls_platform_teardown(ctx);
+}
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 019071b..f923a43 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -45,6 +45,9 @@
 #include "mbedtls/aes.h"
 #include "mbedtls/camellia.h"
 #include "mbedtls/aria.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"
@@ -54,6 +57,7 @@
 #include "mbedtls/ecp.h"
 #include "mbedtls/ecjpake.h"
 #include "mbedtls/timing.h"
+#include "mbedtls/nist_kw.h"
 
 #include <string.h>
 
@@ -205,9 +209,21 @@
 #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)
     {"ccm", mbedtls_ccm_self_test},
 #endif
+#if defined(MBEDTLS_NIST_KW_C) && defined(MBEDTLS_AES_C)
+    {"nist_kw", mbedtls_nist_kw_self_test},
+#endif
 #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/ssl_cert_test.c b/programs/test/ssl_cert_test.c
index 9cfcd2d..fd3526f 100644
--- a/programs/test/ssl_cert_test.c
+++ b/programs/test/ssl_cert_test.c
@@ -29,9 +29,12 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_snprintf   snprintf
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_snprintf        snprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && \
     defined(MBEDTLS_FS_IO) && defined(MBEDTLS_X509_CRL_PARSE_C)
@@ -80,7 +83,8 @@
 
 int main( void )
 {
-    int ret, i;
+    int ret = 1, i;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_x509_crt cacert;
     mbedtls_x509_crl crl;
     char buf[10240];
@@ -210,7 +214,6 @@
         if( ! mbedtls_pk_can_do( &clicert.pk, MBEDTLS_PK_RSA ) )
         {
             mbedtls_printf( " failed\n  !  certificate's key is not RSA\n\n" );
-            ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
             goto exit;
         }
 
@@ -241,6 +244,8 @@
         mbedtls_pk_free( &pk );
     }
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_x509_crt_free( &cacert );
     mbedtls_x509_crl_free( &crl );
@@ -250,7 +255,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_RSA_C && MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO &&
           MBEDTLS_X509_CRL_PARSE_C */
diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c
index 5797f3d..55e0f24 100644
--- a/programs/test/udp_proxy.c
+++ b/programs/test/udp_proxy.c
@@ -37,10 +37,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
-#define mbedtls_time       time
-#define mbedtls_time_t     time_t
-#define mbedtls_printf     printf
-#endif
+#define mbedtls_time            time
+#define mbedtls_time_t          time_t
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_NET_C)
 int main( void )
@@ -600,7 +602,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
 
     mbedtls_net_context listen_fd, client_fd, server_fd;
 
@@ -781,10 +784,12 @@
 
     }
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
 #ifdef MBEDTLS_ERROR_C
-    if( ret != 0 )
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
         char error_buf[100];
         mbedtls_strerror( ret, error_buf, 100 );
@@ -802,7 +807,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret != 0 );
+    return( exit_code );
 }
 
 #endif /* MBEDTLS_NET_C */
diff --git a/programs/util/pem2der.c b/programs/util/pem2der.c
index ad2c6ac..73a9fb5 100644
--- a/programs/util/pem2der.c
+++ b/programs/util/pem2der.c
@@ -29,10 +29,13 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_free       free
-#define mbedtls_calloc    calloc
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_free            free
+#define mbedtls_calloc          calloc
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_FS_IO)
 #include "mbedtls/error.h"
@@ -178,7 +181,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     unsigned char *pem_buffer = NULL;
     unsigned char der_buffer[4096];
     char buf[1024];
@@ -273,6 +277,8 @@
 
     mbedtls_printf( " ok\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     free( pem_buffer );
 
@@ -281,6 +287,6 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BASE64_C && MBEDTLS_FS_IO */
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index c893ca8..c57ecca 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -30,11 +30,13 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
-#define mbedtls_time       time
-#define mbedtls_time_t     time_t
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#endif
+#define mbedtls_time            time
+#define mbedtls_time_t          time_t
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) ||  \
     !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
@@ -145,7 +147,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_net_context server_fd;
     unsigned char buf[1024];
     mbedtls_entropy_context entropy;
@@ -180,7 +183,6 @@
     {
     usage:
         mbedtls_printf( USAGE );
-        ret = 2;
         goto exit;
     }
 
@@ -252,19 +254,23 @@
 
     if( strlen( opt.ca_path ) )
     {
-        ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path );
+        if( ( ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path ) ) < 0 )
+        {
+            mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_path returned -0x%x\n\n", -ret );
+            goto exit;
+        }
+
         verify = 1;
     }
     else if( strlen( opt.ca_file ) )
     {
-        ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file );
-        verify = 1;
-    }
+        if( ( ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ) ) < 0 )
+        {
+            mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file returned -0x%x\n\n", -ret );
+            goto exit;
+        }
 
-    if( ret < 0 )
-    {
-        mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
-        goto exit;
+        verify = 1;
     }
 
     mbedtls_printf( " ok (%d skipped)\n", ret );
@@ -332,8 +338,6 @@
             cur = cur->next;
         }
 
-        ret = 0;
-
         /*
          * 1.3 Verify the certificate
          */
@@ -470,6 +474,8 @@
     else
         goto usage;
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
     mbedtls_net_free( &server_fd );
@@ -485,10 +491,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    if( ret < 0 )
-        ret = 1;
-
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c
index 30df216..a32ac50 100644
--- a/programs/x509/cert_req.c
+++ b/programs/x509/cert_req.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_X509_CSR_WRITE_C) || !defined(MBEDTLS_FS_IO) ||  \
     !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_SHA256_C) || \
@@ -133,7 +136,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_pk_context key;
     char buf[1024];
     int i;
@@ -156,7 +160,6 @@
     {
     usage:
         mbedtls_printf( USAGE );
-        ret = 1;
         goto exit;
     }
 
@@ -317,9 +320,11 @@
 
     mbedtls_printf( " ok\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
 
-    if( ret != 0 && ret != 1)
+    if( exit_code != MBEDTLS_EXIT_SUCCESS )
     {
 #ifdef MBEDTLS_ERROR_C
         mbedtls_strerror( ret, buf, sizeof( buf ) );
@@ -339,7 +344,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_WRITE_C */
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 12baf72..09a91e0 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_X509_CRT_WRITE_C) || \
     !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
@@ -211,7 +214,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     mbedtls_x509_crt issuer_crt;
     mbedtls_pk_context loaded_issuer_key, loaded_subject_key;
     mbedtls_pk_context *issuer_key = &loaded_issuer_key,
@@ -248,7 +252,6 @@
     {
     usage:
         mbedtls_printf( USAGE );
-        ret = 1;
         goto exit;
     }
 
@@ -611,7 +614,6 @@
         {
             mbedtls_printf( " failed\n  !  issuer_key does not match "
                             "issuer certificate\n\n" );
-            ret = -1;
             goto exit;
         }
     }
@@ -784,6 +786,8 @@
 
     mbedtls_printf( " ok\n" );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_x509write_crt_free( &crt );
     mbedtls_pk_free( &loaded_subject_key );
@@ -797,7 +801,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
           MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
diff --git a/programs/x509/crl_app.c b/programs/x509/crl_app.c
index 210d19e..f831683 100644
--- a/programs/x509/crl_app.c
+++ b/programs/x509/crl_app.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) ||  \
     !defined(MBEDTLS_X509_CRL_PARSE_C) || !defined(MBEDTLS_FS_IO)
@@ -67,7 +70,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     unsigned char buf[100000];
     mbedtls_x509_crl crl;
     int i;
@@ -131,6 +135,8 @@
 
     mbedtls_printf( "%s\n", buf );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_x509_crl_free( &crl );
 
@@ -139,7 +145,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_X509_CRL_PARSE_C &&
           MBEDTLS_FS_IO */
diff --git a/programs/x509/req_app.c b/programs/x509/req_app.c
index 8410a53..0f20c85 100644
--- a/programs/x509/req_app.c
+++ b/programs/x509/req_app.c
@@ -29,8 +29,11 @@
 #include "mbedtls/platform.h"
 #else
 #include <stdio.h>
-#define mbedtls_printf     printf
-#endif
+#include <stdlib.h>
+#define mbedtls_printf          printf
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_RSA_C) ||  \
     !defined(MBEDTLS_X509_CSR_PARSE_C) || !defined(MBEDTLS_FS_IO)
@@ -67,7 +70,8 @@
 
 int main( int argc, char *argv[] )
 {
-    int ret = 0;
+    int ret = 1;
+    int exit_code = MBEDTLS_EXIT_FAILURE;
     unsigned char buf[100000];
     mbedtls_x509_csr csr;
     int i;
@@ -131,6 +135,8 @@
 
     mbedtls_printf( "%s\n", buf );
 
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
 exit:
     mbedtls_x509_csr_free( &csr );
 
@@ -139,7 +145,7 @@
     fflush( stdout ); getchar();
 #endif
 
-    return( ret );
+    return( exit_code );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_X509_CSR_PARSE_C &&
           MBEDTLS_FS_IO */
diff --git a/scripts/config.pl b/scripts/config.pl
index 5bf2785..3d2884c 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 #
 # This file is part of mbed TLS (https://tls.mbed.org)
 #
@@ -95,6 +95,7 @@
 MBEDTLS_ZLIB_SUPPORT
 MBEDTLS_PKCS11_C
 MBEDTLS_NO_UDBL_DIVISION
+MBEDTLS_NO_64BIT_MULTIPLICATION
 _ALT\s*$
 );
 
diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl
index 60e5233..ac171ed4a 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # Generate error.c
 #
@@ -30,9 +30,9 @@
 my $error_format_file = $data_dir.'/error.fmt';
 
 my @low_level_modules = qw( AES ARC4 ARIA ASN1 BASE64 BIGNUM BLOWFISH
-                            CAMELLIA CCM CMAC CTR_DRBG DES
+                            CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES
                             ENTROPY GCM HKDF HMAC_DRBG MD2 MD4 MD5
-                            NET OID PADLOCK PBKDF2 RIPEMD160
+                            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/generate_features.pl b/scripts/generate_features.pl
index 2aa695c..1bd82ca 100755
--- a/scripts/generate_features.pl
+++ b/scripts/generate_features.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 #
 
 use strict;
diff --git a/scripts/generate_visualc_files.pl b/scripts/generate_visualc_files.pl
index e042a44..811c71f 100755
--- a/scripts/generate_visualc_files.pl
+++ b/scripts/generate_visualc_files.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # Generate main file, individual apps and solution files for MS Visual Studio
 # 2010
diff --git a/scripts/massif_max.pl b/scripts/massif_max.pl
index d1ce4ca..4e3342a 100755
--- a/scripts/massif_max.pl
+++ b/scripts/massif_max.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # Parse a massif.out.xxx file and output peak total memory usage
 
diff --git a/scripts/rename.pl b/scripts/rename.pl
index c29519e..fb42809 100755
--- a/scripts/rename.pl
+++ b/scripts/rename.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 #
 # This file is part of mbed TLS (https://tls.mbed.org)
 #
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f630edb..52632f8 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -15,6 +15,11 @@
     message(FATAL_ERROR "Cannot build test suites without Perl")
 endif()
 
+# Enable definition of various functions used throughout the testsuite
+# (gethostname, strdup, fileno...) even when compiling with -std=c99. Harmless
+# on non-POSIX platforms.
+add_definitions("-D_POSIX_C_SOURCE=200809L")
+
 function(add_test_suite suite_name)
     if(ARGV1)
         set(data_name ${ARGV1})
@@ -56,11 +61,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)
@@ -92,6 +101,7 @@
 add_test_suite(mdx)
 add_test_suite(memory_buffer_alloc)
 add_test_suite(mpi)
+add_test_suite(nist_kw)
 add_test_suite(pem)
 add_test_suite(pkcs1_v15)
 add_test_suite(pkcs1_v21)
@@ -99,6 +109,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 d65cd93..3632554 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -12,6 +12,11 @@
 		-lmbedx509$(SHARED_SUFFIX)	\
 		-lmbedcrypto$(SHARED_SUFFIX)
 
+# Enable definition of various functions used throughout the testsuite
+# (gethostname, strdup, fileno...) even when compiling with -std=c99. Harmless
+# on non-POSIX platforms.
+LOCAL_CFLAGS += -D_POSIX_C_SOURCE=200809L
+
 ifndef SHARED
 DEP=../library/libmbedcrypto.a ../library/libmbedx509.a ../library/libmbedtls.a
 else
@@ -48,14 +53,16 @@
 APPS =	test_suite_aes.ecb$(EXEXT)	test_suite_aes.cbc$(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_aes.rest$(EXEXT)	test_suite_arc4$(EXEXT)		\
+	test_suite_aria$(EXEXT)		test_suite_asn1write$(EXEXT)	\
 	test_suite_base64$(EXEXT)	test_suite_blowfish$(EXEXT)	\
 	test_suite_camellia$(EXEXT)	test_suite_ccm$(EXEXT)		\
-	test_suite_aria$(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)				\
@@ -81,10 +88,12 @@
 	test_suite_md$(EXEXT)		test_suite_mdx$(EXEXT)		\
 	test_suite_memory_buffer_alloc$(EXEXT)				\
 	test_suite_mpi$(EXEXT)						\
+	test_suite_nist_kw$(EXEXT)						\
 	test_suite_pem$(EXEXT)			test_suite_pkcs1_v15$(EXEXT)	\
 	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)	\
@@ -137,6 +146,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
@@ -261,6 +278,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 $@
@@ -277,6 +302,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 $@
@@ -401,6 +434,10 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test_suite_nist_kw$(EXEXT): test_suite_nist_kw.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test_suite_pem$(EXEXT): test_suite_pem.c $(DEP)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -429,6 +466,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/compat.sh b/tests/compat.sh
index d383cb4..bf65e5e 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -42,6 +42,9 @@
             PEER_GNUTLS=""
         else
             PEER_GNUTLS=" GnuTLS"
+            if [ $MINOR -lt 4 ]; then
+                GNUTLS_MINOR_LT_FOUR='x'
+            fi
         fi
     fi
 else
@@ -58,7 +61,8 @@
 # - RC4, single-DES: requires legacy OpenSSL/GnuTLS versions
 #   avoid plain DES but keep 3DES-EDE-CBC (mbedTLS), DES-CBC3 (OpenSSL)
 # - ARIA: not in default config.h + requires OpenSSL >= 1.1.1
-EXCLUDE='NULL\|DES-CBC-\|RC4\|ARCFOUR\|ARIA'
+# - ChachaPoly: requires OpenSSL >= 1.1.0
+EXCLUDE='NULL\|DES-CBC-\|RC4\|ARCFOUR\|ARIA\|CHACHA20-POLY1305'
 VERBOSE=""
 MEMCHECK=0
 PEERS="OpenSSL$PEER_GNUTLS mbedTLS"
@@ -437,6 +441,9 @@
 # NOTE: for some reason RSA-PSK doesn't work with OpenSSL,
 # so RSA-PSK ciphersuites need to go in other sections, see
 # https://github.com/ARMmbed/mbedtls/issues/1419
+#
+# ChachaPoly suites are here rather than in "common", as they were added in
+# GnuTLS in 3.5.0 and the CI only has 3.4.x so far.
 add_openssl_ciphersuites()
 {
     case $TYPE in
@@ -468,6 +475,7 @@
                     TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384          \
                     TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384        \
                     TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256        \
+                    TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256   \
                     "
                 O_CIPHERS="$O_CIPHERS               \
                     ECDH-ECDSA-AES128-SHA256        \
@@ -476,6 +484,7 @@
                     ECDH-ECDSA-AES256-GCM-SHA384    \
                     ECDHE-ECDSA-ARIA256-GCM-SHA384  \
                     ECDHE-ECDSA-ARIA128-GCM-SHA256  \
+                    ECDHE-ECDSA-CHACHA20-POLY1305   \
                     "
             fi
             ;;
@@ -498,6 +507,8 @@
                     TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256          \
                     TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256            \
                     TLS-RSA-WITH-ARIA-128-GCM-SHA256                \
+                    TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256       \
+                    TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256     \
                     "
                 O_CIPHERS="$O_CIPHERS               \
                     ECDHE-ARIA256-GCM-SHA384        \
@@ -506,6 +517,8 @@
                     ECDHE-ARIA128-GCM-SHA256        \
                     DHE-RSA-ARIA128-GCM-SHA256      \
                     ARIA128-GCM-SHA256              \
+                    DHE-RSA-CHACHA20-POLY1305       \
+                    ECDHE-RSA-CHACHA20-POLY1305     \
                     "
             fi
             ;;
@@ -518,12 +531,18 @@
                     TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256            \
                     TLS-PSK-WITH-ARIA-256-GCM-SHA384                \
                     TLS-PSK-WITH-ARIA-128-GCM-SHA256                \
+                    TLS-PSK-WITH-CHACHA20-POLY1305-SHA256           \
+                    TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256     \
+                    TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256       \
                     "
                 O_CIPHERS="$O_CIPHERS               \
                     DHE-PSK-ARIA256-GCM-SHA384      \
                     DHE-PSK-ARIA128-GCM-SHA256      \
                     PSK-ARIA256-GCM-SHA384          \
                     PSK-ARIA128-GCM-SHA256          \
+                    DHE-PSK-CHACHA20-POLY1305       \
+                    ECDHE-PSK-CHACHA20-POLY1305     \
+                    PSK-CHACHA20-POLY1305           \
                     "
             fi
             ;;
@@ -545,12 +564,20 @@
                     TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384    \
                     TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256    \
                     TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384    \
+                    TLS-ECDHE-ECDSA-WITH-AES-128-CCM                \
+                    TLS-ECDHE-ECDSA-WITH-AES-256-CCM                \
+                    TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8              \
+                    TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8              \
                    "
                 G_CIPHERS="$G_CIPHERS                               \
                     +ECDHE-ECDSA:+CAMELLIA-128-CBC:+SHA256          \
                     +ECDHE-ECDSA:+CAMELLIA-256-CBC:+SHA384          \
                     +ECDHE-ECDSA:+CAMELLIA-128-GCM:+AEAD            \
                     +ECDHE-ECDSA:+CAMELLIA-256-GCM:+AEAD            \
+                    +ECDHE-ECDSA:+AES-128-CCM:+AEAD                 \
+                    +ECDHE-ECDSA:+AES-256-CCM:+AEAD                 \
+                    +ECDHE-ECDSA:+AES-128-CCM-8:+AEAD               \
+                    +ECDHE-ECDSA:+AES-256-CCM-8:+AEAD               \
                    "
             fi
             ;;
@@ -580,6 +607,14 @@
                     TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384    \
                     TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256        \
                     TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384        \
+                    TLS-RSA-WITH-AES-128-CCM                    \
+                    TLS-RSA-WITH-AES-256-CCM                    \
+                    TLS-DHE-RSA-WITH-AES-128-CCM                \
+                    TLS-DHE-RSA-WITH-AES-256-CCM                \
+                    TLS-RSA-WITH-AES-128-CCM-8                  \
+                    TLS-RSA-WITH-AES-256-CCM-8                  \
+                    TLS-DHE-RSA-WITH-AES-128-CCM-8              \
+                    TLS-DHE-RSA-WITH-AES-256-CCM-8              \
                     "
                 G_CIPHERS="$G_CIPHERS                           \
                     +ECDHE-RSA:+CAMELLIA-128-CBC:+SHA256        \
@@ -594,6 +629,14 @@
                     +DHE-RSA:+CAMELLIA-256-GCM:+AEAD            \
                     +RSA:+CAMELLIA-128-GCM:+AEAD                \
                     +RSA:+CAMELLIA-256-GCM:+AEAD                \
+                    +RSA:+AES-128-CCM:+AEAD                     \
+                    +RSA:+AES-256-CCM:+AEAD                     \
+                    +RSA:+AES-128-CCM-8:+AEAD                   \
+                    +RSA:+AES-256-CCM-8:+AEAD                   \
+                    +DHE-RSA:+AES-128-CCM:+AEAD                 \
+                    +DHE-RSA:+AES-256-CCM:+AEAD                 \
+                    +DHE-RSA:+AES-128-CCM-8:+AEAD               \
+                    +DHE-RSA:+AES-256-CCM-8:+AEAD               \
                     "
             fi
             ;;
@@ -665,6 +708,14 @@
                     TLS-PSK-WITH-AES-256-GCM-SHA384             \
                     TLS-DHE-PSK-WITH-AES-128-GCM-SHA256         \
                     TLS-DHE-PSK-WITH-AES-256-GCM-SHA384         \
+                    TLS-PSK-WITH-AES-128-CCM                    \
+                    TLS-PSK-WITH-AES-256-CCM                    \
+                    TLS-DHE-PSK-WITH-AES-128-CCM                \
+                    TLS-DHE-PSK-WITH-AES-256-CCM                \
+                    TLS-PSK-WITH-AES-128-CCM-8                  \
+                    TLS-PSK-WITH-AES-256-CCM-8                  \
+                    TLS-DHE-PSK-WITH-AES-128-CCM-8              \
+                    TLS-DHE-PSK-WITH-AES-256-CCM-8              \
                     TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256    \
                     TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384    \
                     TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256        \
@@ -695,6 +746,14 @@
                     +PSK:+AES-256-GCM:+AEAD                     \
                     +DHE-PSK:+AES-128-GCM:+AEAD                 \
                     +DHE-PSK:+AES-256-GCM:+AEAD                 \
+                    +PSK:+AES-128-CCM:+AEAD                     \
+                    +PSK:+AES-256-CCM:+AEAD                     \
+                    +DHE-PSK:+AES-128-CCM:+AEAD                 \
+                    +DHE-PSK:+AES-256-CCM:+AEAD                 \
+                    +PSK:+AES-128-CCM-8:+AEAD                   \
+                    +PSK:+AES-256-CCM-8:+AEAD                   \
+                    +DHE-PSK:+AES-128-CCM-8:+AEAD               \
+                    +DHE-PSK:+AES-256-CCM-8:+AEAD               \
                     +RSA-PSK:+CAMELLIA-128-GCM:+AEAD            \
                     +RSA-PSK:+CAMELLIA-256-GCM:+AEAD            \
                     +PSK:+CAMELLIA-128-GCM:+AEAD                \
@@ -737,10 +796,6 @@
                 M_CIPHERS="$M_CIPHERS                               \
                     TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256     \
                     TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384     \
-                    TLS-ECDHE-ECDSA-WITH-AES-128-CCM                \
-                    TLS-ECDHE-ECDSA-WITH-AES-256-CCM                \
-                    TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8              \
-                    TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8              \
                     TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384        \
                     TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256        \
                     TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384         \
@@ -755,14 +810,6 @@
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
                 M_CIPHERS="$M_CIPHERS                               \
-                    TLS-RSA-WITH-AES-128-CCM                        \
-                    TLS-RSA-WITH-AES-256-CCM                        \
-                    TLS-DHE-RSA-WITH-AES-128-CCM                    \
-                    TLS-DHE-RSA-WITH-AES-256-CCM                    \
-                    TLS-RSA-WITH-AES-128-CCM-8                      \
-                    TLS-RSA-WITH-AES-256-CCM-8                      \
-                    TLS-DHE-RSA-WITH-AES-128-CCM-8                  \
-                    TLS-DHE-RSA-WITH-AES-256-CCM-8                  \
                     TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384          \
                     TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384            \
                     TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256          \
@@ -789,14 +836,6 @@
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
                 M_CIPHERS="$M_CIPHERS                               \
-                    TLS-PSK-WITH-AES-128-CCM                        \
-                    TLS-PSK-WITH-AES-256-CCM                        \
-                    TLS-DHE-PSK-WITH-AES-128-CCM                    \
-                    TLS-DHE-PSK-WITH-AES-256-CCM                    \
-                    TLS-PSK-WITH-AES-128-CCM-8                      \
-                    TLS-PSK-WITH-AES-256-CCM-8                      \
-                    TLS-DHE-PSK-WITH-AES-128-CCM-8                  \
-                    TLS-DHE-PSK-WITH-AES-256-CCM-8                  \
                     TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384            \
                     TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256            \
                     TLS-PSK-WITH-ARIA-256-CBC-SHA384                \
@@ -807,6 +846,7 @@
                     TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256          \
                     TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384            \
                     TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256            \
+                    TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256       \
                     "
             fi
             ;;
@@ -842,10 +882,17 @@
             exit 1;
     esac
 
+    # GnuTLS < 3.4 will choke if we try to allow CCM-8
+    if [ -z "${GNUTLS_MINOR_LT_FOUR-}" ]; then
+        G_PRIO_CCM="+AES-256-CCM-8:+AES-128-CCM-8:"
+    else
+        G_PRIO_CCM=""
+    fi
+
     M_SERVER_ARGS="server_port=$PORT server_addr=0.0.0.0 force_version=$MODE arc4=1"
     O_SERVER_ARGS="-accept $PORT -cipher NULL,ALL -$MODE -dhparam data_files/dhparams.pem"
     G_SERVER_ARGS="-p $PORT --http $G_MODE"
-    G_SERVER_PRIO="NORMAL:+ARCFOUR-128:+NULL:+MD5:+PSK:+DHE-PSK:+ECDHE-PSK:+RSA-PSK:-VERS-TLS-ALL:$G_PRIO_MODE"
+    G_SERVER_PRIO="NORMAL:${G_PRIO_CCM}+ARCFOUR-128:+NULL:+MD5:+PSK:+DHE-PSK:+ECDHE-PSK:+RSA-PSK:-VERS-TLS-ALL:$G_PRIO_MODE"
 
     # with OpenSSL 1.0.1h, -www, -WWW and -HTTP break DTLS handshakes
     if is_dtls "$MODE"; then
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 8ae720e..d7d5a8c 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -35,6 +35,7 @@
 #   * GNU Make
 #   * CMake
 #   * GCC and Clang (recent enough for using ASan with gcc and MemSan with clang, or valgrind)
+#   * G++
 #   * arm-gcc and mingw-gcc
 #   * ArmCC 5 and ArmCC 6, unless invoked with --no-armcc
 #   * Yotta build dependencies, unless invoked with --no-yotta
@@ -220,13 +221,21 @@
 check_tools()
 {
     for TOOL in "$@"; do
-        if ! `hash "$TOOL" >/dev/null 2>&1`; then
+        if ! `type "$TOOL" >/dev/null 2>&1`; then
             err_msg "$TOOL not found!"
             exit 1
         fi
     done
 }
 
+check_headers_in_cpp () {
+    ls include/mbedtls >headers.txt
+    <programs/test/cpp_dummy_build.cpp sed -n 's/"$//; s!^#include "mbedtls/!!p' |
+    sort |
+    diff headers.txt -
+    rm headers.txt
+}
+
 while [ $# -gt 0 ]; do
     case "$1" in
         --armcc) RUN_ARMCC=1;;
@@ -339,6 +348,7 @@
             echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
             echo "${start_red}FAILED: $failure_count${end_color}$failure_summary"
             echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+            exit 1
         elif [ -z "${1-}" ]; then
             echo "SUCCESS :)"
         fi
@@ -357,6 +367,12 @@
     fi
 }
 
+# to be used instead of ! for commands run with
+# record_status or if_build_succeeded
+not() {
+    ! "$@"
+}
+
 msg "info: $0 configuration"
 echo "MEMORY: $MEMORY"
 echo "FORCE: $FORCE"
@@ -520,6 +536,28 @@
 msg "test: RSA_NO_CRT - RSA-related part of compat.sh (ASan build)" # ~ 3 min
 tests/compat.sh -t RSA
 
+msg "build: small SSL_OUT_CONTENT_LEN (ASan build)"
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl set MBEDTLS_SSL_IN_CONTENT_LEN 16384
+scripts/config.pl set MBEDTLS_SSL_OUT_CONTENT_LEN 4096
+CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+make
+
+msg "test: small SSL_OUT_CONTENT_LEN - ssl-opt.sh MFL and large packet tests"
+if_build_succeeded tests/ssl-opt.sh -f "Max fragment\|Large packet"
+
+msg "build: small SSL_IN_CONTENT_LEN (ASan build)"
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl set MBEDTLS_SSL_IN_CONTENT_LEN 4096
+scripts/config.pl set MBEDTLS_SSL_OUT_CONTENT_LEN 16384
+CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+make
+
+msg "test: small SSL_IN_CONTENT_LEN - ssl-opt.sh MFL tests"
+if_build_succeeded tests/ssl-opt.sh -f "Max fragment"
+
 msg "build: cmake, full config, clang" # ~ 50s
 cleanup
 cp "$CONFIG_H" "$CONFIG_BAK"
@@ -537,8 +575,26 @@
 msg "test: compat.sh RC4, DES & NULL (full config)" # ~ 2 min
 if_build_succeeded env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES\|RC4\|ARCFOUR'
 
-msg "test: compat.sh ARIA"
-if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA'
+msg "test: compat.sh ARIA + ChachaPoly"
+if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
+
+msg "build: make, full config + DEPRECATED_WARNING, gcc -O" # ~ 30s
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl full
+scripts/config.pl set MBEDTLS_DEPRECATED_WARNING
+# Build with -O -Wextra to catch a maximum of issues.
+make CC=gcc CFLAGS='-O -Werror -Wall -Wextra' lib programs
+make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
+
+msg "build: make, full config + DEPRECATED_REMOVED, clang -O" # ~ 30s
+# No cleanup, just tweak the configuration and rebuild
+make clean
+scripts/config.pl unset MBEDTLS_DEPRECATED_WARNING
+scripts/config.pl set MBEDTLS_DEPRECATED_REMOVED
+# Build with -O -Wextra to catch a maximum of issues.
+make CC=clang CFLAGS='-O -Werror -Wall -Wextra' lib programs
+make CC=clang CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
 
 msg "test/build: curves.pl (gcc)" # ~ 4 min
 cleanup
@@ -560,6 +616,12 @@
 cleanup
 make CC=gcc CFLAGS='-Werror -Wall -Wextra -Os'
 
+msg "test: verify header list in cpp_dummy_build.cpp"
+record_status check_headers_in_cpp
+
+msg "build: Unix make, incremental g++"
+make TEST_CPP=1
+
 # Full configuration build, without platform support, file IO and net sockets.
 # This should catch missing mbedtls_printf definitions, and by disabling file
 # IO, it should catch missing '#include <stdio.h>'
@@ -616,6 +678,7 @@
 scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY # uses syscall() on GNU/Linux
 make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0 -std=c99 -pedantic' lib
 
+# Run max fragment length tests with MFL disabled
 msg "build: default config except MFL extension (ASan build)" # ~ 30s
 cleanup
 cp "$CONFIG_H" "$CONFIG_BAK"
@@ -626,6 +689,18 @@
 msg "test: ssl-opt.sh, MFL-related tests"
 if_build_succeeded tests/ssl-opt.sh -f "Max fragment length"
 
+msg "build: no MFL extension, small SSL_OUT_CONTENT_LEN (ASan build)"
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl unset MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+scripts/config.pl set MBEDTLS_SSL_IN_CONTENT_LEN 16384
+scripts/config.pl set MBEDTLS_SSL_OUT_CONTENT_LEN 4096
+CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+make
+
+msg "test: MFL tests (disabled MFL extension case) & large packet tests"
+if_build_succeeded tests/ssl-opt.sh -f "Max fragment length\|Large buffer"
+
 msg "build: default config with  MBEDTLS_TEST_NULL_ENTROPY (ASan build)"
 cleanup
 cp "$CONFIG_H" "$CONFIG_BAK"
@@ -676,15 +751,30 @@
 fi
 
 if uname -a | grep -F x86_64 >/dev/null; then
-    msg "build: i386, make, gcc" # ~ 30s
+    # Build once with -O0, to compile out the i386 specific inline assembly
+    msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     cleanup
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -m32'
+    cp "$CONFIG_H" "$CONFIG_BAK"
+    scripts/config.pl full
+    make CC=gcc CFLAGS='-O0 -Werror -Wall -Wextra -m32 -fsanitize=address'
 
-    msg "test: i386, make, gcc"
+    msg "test: i386, make, gcc -O0 (ASan build)"
+    make test
+
+    # Build again with -O1, to compile in the i386 specific inline assembly
+    msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s
+    cleanup
+    cp "$CONFIG_H" "$CONFIG_BAK"
+    scripts/config.pl full
+    make CC=gcc CFLAGS='-O1 -Werror -Wall -Wextra -m32 -fsanitize=address'
+
+    msg "test: i386, make, gcc -O1 (ASan build)"
     make test
 
     msg "build: 64-bit ILP32, make, gcc" # ~ 30s
     cleanup
+    cp "$CONFIG_H" "$CONFIG_BAK"
+    scripts/config.pl full
     make CC=gcc CFLAGS='-Werror -Wall -Wextra -mx32'
 
     msg "test: 64-bit ILP32, make, gcc"
@@ -713,6 +803,31 @@
 msg "test: gcc, force 64-bit bignum limbs"
 make test
 
+
+msg "build: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl full
+scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
+scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION
+make CFLAGS='-Werror -O1'
+
+msg "test: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s
+make test
+
+
+msg "build: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl full
+scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
+scripts/config.pl set MBEDTLS_NO_64BIT_MULTIPLICATION
+make CFLAGS='-Werror -O1'
+
+msg "test: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s
+make test
+
+
 msg "build: arm-none-eabi-gcc, make" # ~ 10s
 cleanup
 cp "$CONFIG_H" "$CONFIG_BAK"
@@ -748,7 +863,27 @@
 scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION
 make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib
 echo "Checking that software 64-bit division is not required"
-! grep __aeabi_uldiv library/*.o
+if_build_succeeded not grep __aeabi_uldiv library/*.o
+
+msg "build: arm-none-eabi-gcc MBEDTLS_NO_64BIT_MULTIPLICATION, make" # ~ 10s
+cleanup
+cp "$CONFIG_H" "$CONFIG_BAK"
+scripts/config.pl full
+scripts/config.pl unset MBEDTLS_NET_C
+scripts/config.pl unset MBEDTLS_TIMING_C
+scripts/config.pl unset MBEDTLS_FS_IO
+scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
+scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY
+# following things are not in the default config
+scripts/config.pl unset MBEDTLS_HAVEGE_C # depends on timing.c
+scripts/config.pl unset MBEDTLS_THREADING_PTHREAD
+scripts/config.pl unset MBEDTLS_THREADING_C
+scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # execinfo.h
+scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # calls exit
+scripts/config.pl set MBEDTLS_NO_64BIT_MULTIPLICATION
+make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -O1 -march=armv6-m -mthumb' lib
+echo "Checking that software 64-bit multiplication is not required"
+if_build_succeeded not grep __aeabi_lmul library/*.o
 
 msg "build: ARM Compiler 5, make"
 cleanup
@@ -896,12 +1031,22 @@
 rm -rf "$OUT_OF_SOURCE_DIR"
 unset MBEDTLS_ROOT_DIR
 
+# Test that the function mbedtls_platform_zeroize() is not optimized away by
+# different combinations of compilers and optimization flags by using an
+# auxiliary GDB script. Unfortunately, GDB does not return error values to the
+# system in all cases that the script fails, so we must manually search the
+# output to check whether the pass string is present and no failure strings
+# were printed.
 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
+        make programs CC="$compiler" DEBUG=1 CFLAGS="$optimization_flag"
+        if_build_succeeded gdb -x tests/scripts/test_zeroize.gdb -nw -batch -nx 2>&1 | tee test_zeroize.log
+        if_build_succeeded [ -s test_zeroize.log ]
+        if_build_succeeded grep "The buffer was correctly zeroized" test_zeroize.log
+        if_build_succeeded not grep -i "error" test_zeroize.log
+        rm -f test_zeroize.log
     done
 done
 
diff --git a/tests/scripts/check-doxy-blocks.pl b/tests/scripts/check-doxy-blocks.pl
index b0fd696..4967699 100755
--- a/tests/scripts/check-doxy-blocks.pl
+++ b/tests/scripts/check-doxy-blocks.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # Detect comment blocks that are likely meant to be doxygen blocks but aren't.
 #
diff --git a/tests/scripts/curves.pl b/tests/scripts/curves.pl
index 0041814..ddc90c5 100755
--- a/tests/scripts/curves.pl
+++ b/tests/scripts/curves.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # curves.pl
 #
diff --git a/tests/scripts/depends-hashes.pl b/tests/scripts/depends-hashes.pl
index 29dcfb0..f57e7ed 100755
--- a/tests/scripts/depends-hashes.pl
+++ b/tests/scripts/depends-hashes.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # depends-hashes.pl
 #
diff --git a/tests/scripts/depends-pkalgs.pl b/tests/scripts/depends-pkalgs.pl
index 14c92b2..97a43e8 100755
--- a/tests/scripts/depends-pkalgs.pl
+++ b/tests/scripts/depends-pkalgs.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # depends-pkalgs.pl
 #
diff --git a/tests/scripts/gen_ctr_drbg.pl b/tests/scripts/gen_ctr_drbg.pl
index ee13024..3c074be 100755
--- a/tests/scripts/gen_ctr_drbg.pl
+++ b/tests/scripts/gen_ctr_drbg.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 #
 # Based on NIST CTR_DRBG.rsp validation file
 # Only uses AES-256-CTR cases that use a Derivation function
diff --git a/tests/scripts/gen_gcm_decrypt.pl b/tests/scripts/gen_gcm_decrypt.pl
index 6decac2..03809cb 100755
--- a/tests/scripts/gen_gcm_decrypt.pl
+++ b/tests/scripts/gen_gcm_decrypt.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 #
 # Based on NIST gcmDecryptxxx.rsp validation files
 # Only first 3 of every set used for compile time saving
diff --git a/tests/scripts/gen_gcm_encrypt.pl b/tests/scripts/gen_gcm_encrypt.pl
index 8adbbce..29ec677 100755
--- a/tests/scripts/gen_gcm_encrypt.pl
+++ b/tests/scripts/gen_gcm_encrypt.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 #
 # Based on NIST gcmEncryptIntIVxxx.rsp validation files
 # Only first 3 of every set used for compile time saving
diff --git a/tests/scripts/gen_pkcs1_v21_sign_verify.pl b/tests/scripts/gen_pkcs1_v21_sign_verify.pl
index 678e2f9..110cb4b 100755
--- a/tests/scripts/gen_pkcs1_v21_sign_verify.pl
+++ b/tests/scripts/gen_pkcs1_v21_sign_verify.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 #
 
 use strict;
diff --git a/tests/scripts/key-exchanges.pl b/tests/scripts/key-exchanges.pl
index d167c67..3bf7ae3 100755
--- a/tests/scripts/key-exchanges.pl
+++ b/tests/scripts/key-exchanges.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # key-exchanges.pl
 #
diff --git a/tests/scripts/list-enum-consts.pl b/tests/scripts/list-enum-consts.pl
index 633e3fd..21c25b3 100755
--- a/tests/scripts/list-enum-consts.pl
+++ b/tests/scripts/list-enum-consts.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 use warnings;
 use strict;
diff --git a/tests/scripts/recursion.pl b/tests/scripts/recursion.pl
index 3ad42b1..431e592 100755
--- a/tests/scripts/recursion.pl
+++ b/tests/scripts/recursion.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # Find functions making recursive calls to themselves.
 # (Multiple recursion where a() calls b() which calls a() not covered.)
diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl
index 7e2974b..6279358 100755
--- a/tests/scripts/run-test-suites.pl
+++ b/tests/scripts/run-test-suites.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # run-test-suites.pl
 #
diff --git a/tests/scripts/test-ref-configs.pl b/tests/scripts/test-ref-configs.pl
index b07329c..80d5f38 100755
--- a/tests/scripts/test-ref-configs.pl
+++ b/tests/scripts/test-ref-configs.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # test-ref-configs.pl
 #
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 2366117..937a27b 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -21,6 +21,11 @@
 
 set -u
 
+if cd $( dirname $0 ); then :; else
+    echo "cd $( dirname $0 ) failed" >&2
+    exit 1
+fi
+
 # default values, can be overriden by the environment
 : ${P_SRV:=../programs/ssl/ssl_server2}
 : ${P_CLI:=../programs/ssl/ssl_client2}
@@ -178,6 +183,25 @@
     fi
 }
 
+# Calculate the input & output maximum content lengths set in the config
+MAX_CONTENT_LEN=$( ../scripts/config.pl get MBEDTLS_SSL_MAX_CONTENT_LEN || echo "16384")
+MAX_IN_LEN=$( ../scripts/config.pl get MBEDTLS_SSL_IN_CONTENT_LEN || echo "$MAX_CONTENT_LEN")
+MAX_OUT_LEN=$( ../scripts/config.pl get MBEDTLS_SSL_OUT_CONTENT_LEN || echo "$MAX_CONTENT_LEN")
+
+if [ "$MAX_IN_LEN" -lt "$MAX_CONTENT_LEN" ]; then
+    MAX_CONTENT_LEN="$MAX_IN_LEN"
+fi
+if [ "$MAX_OUT_LEN" -lt "$MAX_CONTENT_LEN" ]; then
+    MAX_CONTENT_LEN="$MAX_OUT_LEN"
+fi
+
+# skip the next test if the SSL output buffer is less than 16KB
+requires_full_size_output_buffer() {
+    if [ "$MAX_OUT_LEN" -ne 16384 ]; then
+        SKIP_NEXT="YES"
+    fi
+}
+
 # skip the next test if valgrind is in use
 not_with_valgrind() {
     if [ "$MEMCHECK" -gt 0 ]; then
@@ -308,7 +332,7 @@
         done
     }
 else
-    echo "Warning: lsof not available, wait_server_start = sleep $START_DELAY"
+    echo "Warning: lsof not available, wait_server_start = sleep"
     wait_server_start() {
         sleep "$START_DELAY"
     }
@@ -626,11 +650,6 @@
 # MAIN
 #
 
-if cd $( dirname $0 ); then :; else
-    echo "cd $( dirname $0 ) failed" >&2
-    exit 1
-fi
-
 get_options "$@"
 
 # sanity checks, avoid an avalanche of errors
@@ -723,7 +742,7 @@
             "$P_CLI" \
             0 \
             -s "Protocol is TLSv1.2" \
-            -s "Ciphersuite is TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" \
+            -s "Ciphersuite is TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256" \
             -s "client hello v3, signature_algorithm ext: 6" \
             -s "ECDHE curve: secp521r1" \
             -S "error" \
@@ -734,20 +753,14 @@
             "$P_CLI dtls=1" \
             0 \
             -s "Protocol is DTLSv1.2" \
-            -s "Ciphersuite is TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384"
+            -s "Ciphersuite is TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256"
 
 # Test current time in ServerHello
 requires_config_enabled MBEDTLS_HAVE_TIME
-run_test    "Default, ServerHello contains gmt_unix_time" \
+run_test    "ServerHello contains gmt_unix_time" \
             "$P_SRV debug_level=3" \
             "$P_CLI debug_level=3" \
             0 \
-            -s "Protocol is TLSv1.2" \
-            -s "Ciphersuite is TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" \
-            -s "client hello v3, signature_algorithm ext: 6" \
-            -s "ECDHE curve: secp521r1" \
-            -S "error" \
-            -C "error" \
             -f "check_server_hello_time" \
             -F "check_server_hello_time"
 
@@ -1157,6 +1170,38 @@
             -s "received FALLBACK_SCSV" \
             -S "inapropriate fallback"
 
+# Test sending and receiving empty application data records
+
+run_test    "Encrypt then MAC: empty application data record" \
+            "$P_SRV auth_mode=none debug_level=4 etm=1" \
+            "$P_CLI auth_mode=none etm=1 request_size=0 force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA" \
+            0 \
+            -S "0000:  0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f" \
+            -s "dumping 'input payload after decrypt' (0 bytes)" \
+            -c "0 bytes written in 1 fragments"
+
+run_test    "Default, no Encrypt then MAC: empty application data record" \
+            "$P_SRV auth_mode=none debug_level=4 etm=0" \
+            "$P_CLI auth_mode=none etm=0 request_size=0" \
+            0 \
+            -s "dumping 'input payload after decrypt' (0 bytes)" \
+            -c "0 bytes written in 1 fragments"
+
+run_test    "Encrypt then MAC, DTLS: empty application data record" \
+            "$P_SRV auth_mode=none debug_level=4 etm=1 dtls=1" \
+            "$P_CLI auth_mode=none etm=1 request_size=0 force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA dtls=1" \
+            0 \
+            -S "0000:  0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f" \
+            -s "dumping 'input payload after decrypt' (0 bytes)" \
+            -c "0 bytes written in 1 fragments"
+
+run_test    "Default, no Encrypt then MAC, DTLS: empty application data record" \
+            "$P_SRV auth_mode=none debug_level=4 etm=0 dtls=1" \
+            "$P_CLI auth_mode=none etm=0 request_size=0 dtls=1" \
+            0 \
+            -s "dumping 'input payload after decrypt' (0 bytes)" \
+            -c "0 bytes written in 1 fragments"
+
 ## ClientHello generated with
 ## "openssl s_client -CAfile tests/data_files/test-ca.crt -tls1_1 -connect localhost:4433 -cipher ..."
 ## then manually twiddling the ciphersuite list.
@@ -1416,28 +1461,22 @@
 
 # Tests for Max Fragment Length extension
 
-MAX_CONTENT_LEN_EXPECT='16384'
-MAX_CONTENT_LEN_CONFIG=$( ../scripts/config.pl get MBEDTLS_SSL_MAX_CONTENT_LEN)
-
-if [ -n "$MAX_CONTENT_LEN_CONFIG" ] && [ "$MAX_CONTENT_LEN_CONFIG" -ne "$MAX_CONTENT_LEN_EXPECT" ]; then
-    printf "The ${CONFIG_H} file contains a value for the configuration of\n"
-    printf "MBEDTLS_SSL_MAX_CONTENT_LEN that is different from the script’s\n"
-    printf "test value of ${MAX_CONTENT_LEN_EXPECT}. \n"
-    printf "\n"
-    printf "The tests assume this value and if it changes, the tests in this\n"
-    printf "script should also be adjusted.\n"
-    printf "\n"
-
+if [ "$MAX_CONTENT_LEN" -lt "4096" ]; then
+    printf "${CONFIG_H} defines MBEDTLS_SSL_MAX_CONTENT_LEN to be less than 4096. Fragment length tests will fail.\n"
     exit 1
 fi
 
+if [ $MAX_CONTENT_LEN -ne 16384 ]; then
+    printf "Using non-default maximum content length $MAX_CONTENT_LEN\n"
+fi
+
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: enabled, default" \
             "$P_SRV debug_level=3" \
             "$P_CLI debug_level=3" \
             0 \
-            -c "Maximum fragment length is 16384" \
-            -s "Maximum fragment length is 16384" \
+            -c "Maximum fragment length is $MAX_CONTENT_LEN" \
+            -s "Maximum fragment length is $MAX_CONTENT_LEN" \
             -C "client hello, adding max_fragment_length extension" \
             -S "found max fragment length extension" \
             -S "server hello, max_fragment_length extension" \
@@ -1446,46 +1485,50 @@
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: enabled, default, larger message" \
             "$P_SRV debug_level=3" \
-            "$P_CLI debug_level=3 request_size=16385" \
+            "$P_CLI debug_level=3 request_size=$(( $MAX_CONTENT_LEN + 1))" \
             0 \
-            -c "Maximum fragment length is 16384" \
-            -s "Maximum fragment length is 16384" \
+            -c "Maximum fragment length is $MAX_CONTENT_LEN" \
+            -s "Maximum fragment length is $MAX_CONTENT_LEN" \
             -C "client hello, adding max_fragment_length extension" \
             -S "found max fragment length extension" \
             -S "server hello, max_fragment_length extension" \
             -C "found max_fragment_length extension" \
-            -c "16385 bytes written in 2 fragments" \
-            -s "16384 bytes read" \
+            -c "$(( $MAX_CONTENT_LEN + 1)) bytes written in 2 fragments" \
+            -s "$MAX_CONTENT_LEN bytes read" \
             -s "1 bytes read"
 
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length, DTLS: enabled, default, larger message" \
             "$P_SRV debug_level=3 dtls=1" \
-            "$P_CLI debug_level=3 dtls=1 request_size=16385" \
+            "$P_CLI debug_level=3 dtls=1 request_size=$(( $MAX_CONTENT_LEN + 1))" \
             1 \
-            -c "Maximum fragment length is 16384" \
-            -s "Maximum fragment length is 16384" \
+            -c "Maximum fragment length is $MAX_CONTENT_LEN" \
+            -s "Maximum fragment length is $MAX_CONTENT_LEN" \
             -C "client hello, adding max_fragment_length extension" \
             -S "found max fragment length extension" \
             -S "server hello, max_fragment_length extension" \
             -C "found max_fragment_length extension" \
             -c "fragment larger than.*maximum "
 
+# Run some tests with MBEDTLS_SSL_MAX_FRAGMENT_LENGTH disabled
+# (session fragment length will be 16384 regardless of mbedtls
+# content length configuration.)
+
 requires_config_disabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: disabled, larger message" \
             "$P_SRV debug_level=3" \
-            "$P_CLI debug_level=3 request_size=16385" \
+            "$P_CLI debug_level=3 request_size=$(( $MAX_CONTENT_LEN + 1))" \
             0 \
             -C "Maximum fragment length is 16384" \
             -S "Maximum fragment length is 16384" \
-            -c "16385 bytes written in 2 fragments" \
-            -s "16384 bytes read" \
+            -c "$(( $MAX_CONTENT_LEN + 1)) bytes written in 2 fragments" \
+            -s "$MAX_CONTENT_LEN bytes read" \
             -s "1 bytes read"
 
 requires_config_disabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length DTLS: disabled, larger message" \
             "$P_SRV debug_level=3 dtls=1" \
-            "$P_CLI debug_level=3 dtls=1 request_size=16385" \
+            "$P_CLI debug_level=3 dtls=1 request_size=$(( $MAX_CONTENT_LEN + 1))" \
             1 \
             -C "Maximum fragment length is 16384" \
             -S "Maximum fragment length is 16384" \
@@ -1508,7 +1551,7 @@
             "$P_SRV debug_level=3 max_frag_len=4096" \
             "$P_CLI debug_level=3" \
             0 \
-            -c "Maximum fragment length is 16384" \
+            -c "Maximum fragment length is $MAX_CONTENT_LEN" \
             -s "Maximum fragment length is 4096" \
             -C "client hello, adding max_fragment_length extension" \
             -S "found max fragment length extension" \
@@ -2376,6 +2419,7 @@
     exit 1
 fi
 
+requires_full_size_output_buffer
 run_test    "Authentication: server max_int chain, client default" \
             "$P_SRV crt_file=data_files/dir-maxpath/c09.pem \
                     key_file=data_files/dir-maxpath/09.key" \
@@ -2383,6 +2427,7 @@
             0 \
             -C "X509 - A fatal error occured"
 
+requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client default" \
             "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \
                     key_file=data_files/dir-maxpath/10.key" \
@@ -2390,6 +2435,7 @@
             1 \
             -c "X509 - A fatal error occured"
 
+requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client optional" \
             "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \
                     key_file=data_files/dir-maxpath/10.key" \
@@ -2398,6 +2444,7 @@
             1 \
             -c "X509 - A fatal error occured"
 
+requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client none" \
             "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \
                     key_file=data_files/dir-maxpath/10.key" \
@@ -2406,6 +2453,7 @@
             0 \
             -C "X509 - A fatal error occured"
 
+requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server default" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt" \
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
@@ -2413,6 +2461,7 @@
             0 \
             -S "X509 - A fatal error occured"
 
+requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server optional" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=optional" \
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
@@ -2420,6 +2469,7 @@
             1 \
             -s "X509 - A fatal error occured"
 
+requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server required" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=required" \
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
@@ -2427,6 +2477,7 @@
             1 \
             -s "X509 - A fatal error occured"
 
+requires_full_size_output_buffer
 run_test    "Authentication: client max_int chain, server required" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=required" \
             "$P_CLI crt_file=data_files/dir-maxpath/c09.pem \
@@ -3970,14 +4021,19 @@
 
 # Test for large packets
 
+# How many fragments do we expect to write $1 bytes?
+fragments_for_write() {
+    echo "$(( ( $1 + $MAX_OUT_LEN - 1 ) / $MAX_OUT_LEN ))"
+}
+
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
 run_test    "Large packet SSLv3 BlockCipher" \
             "$P_SRV min_version=ssl3" \
             "$P_CLI request_size=16384 force_version=ssl3 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
 run_test    "Large packet SSLv3 StreamCipher" \
@@ -3985,23 +4041,23 @@
             "$P_CLI request_size=16384 force_version=ssl3 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.0 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.0 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1 etm=0 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.0 BlockCipher, truncated MAC" \
@@ -4009,8 +4065,8 @@
             "$P_CLI request_size=16384 force_version=tls1 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.0 BlockCipher, without EtM, truncated MAC" \
@@ -4018,21 +4074,21 @@
             "$P_CLI request_size=16384 force_version=tls1 etm=0 recsplit=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.0 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.0 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.0 StreamCipher, truncated MAC" \
@@ -4040,7 +4096,7 @@
             "$P_CLI request_size=16384 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.0 StreamCipher, without EtM, truncated MAC" \
@@ -4048,23 +4104,23 @@
             "$P_CLI request_size=16384 force_version=tls1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.1 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.1 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_1 etm=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.1 BlockCipher, truncated MAC" \
@@ -4072,7 +4128,7 @@
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.1 BlockCipher, without EtM, truncated MAC" \
@@ -4080,23 +4136,23 @@
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.1 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.1 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.1 StreamCipher, truncated MAC" \
@@ -4104,7 +4160,7 @@
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.1 StreamCipher, without EtM, truncated MAC" \
@@ -4112,31 +4168,31 @@
             "$P_CLI request_size=16384 force_version=tls1_1 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.2 BlockCipher" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.2 BlockCipher, without EtM" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 etm=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.2 BlockCipher larger MAC" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.2 BlockCipher, truncated MAC" \
@@ -4144,7 +4200,7 @@
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
@@ -4152,23 +4208,23 @@
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.2 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.2 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.2 StreamCipher, truncated MAC" \
@@ -4176,7 +4232,7 @@
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             0 \
-            -s "Read from client: 16384 bytes read"
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
@@ -4184,24 +4240,24 @@
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.2 AEAD" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large packet TLS 1.2 AEAD shorter tag" \
             "$P_SRV" \
             "$P_CLI request_size=16384 force_version=tls1_2 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
             0 \
-            -c "16384 bytes written in 1 fragments" \
-            -s "Read from client: 16384 bytes read"
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 # Tests of asynchronous private key support in SSL
 
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index f82694a..8f04885 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -36,6 +36,7 @@
 
 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
 #include <unistd.h>
+#include <strings.h>
 #endif
 
 /*----------------------------------------------------------------------------*/
diff --git a/tests/suites/test_suite_aria.data b/tests/suites/test_suite_aria.data
index 46c6ecc..8cb2d2a 100644
--- a/tests/suites/test_suite_aria.data
+++ b/tests/suites/test_suite_aria.data
@@ -93,3 +93,6 @@
 
 ARIA-256-CFB128 Decrypt - Official Test Vectors 1.0
 aria_decrypt_cfb128:"00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff":"0f1e2d3c4b5a69788796a5b4c3d2e1f0":"26834705b0f2c0e2588d4a7f09009635f28bb93d8c31f870ec1e0bdb082b66fa402dd9c202be300c4517d196b14d4ce11dce97f7aaba54341b0d872cc9b63753a3e8556a14be6f7b3e27e3cfc39caf80f2a355aa50dc83c09c7b11828694f8e4aa726c528976b53f2c877f4991a3a8d28adb63bd751846ffb2350265e179d4990753ae8485ff9b4133ddad5875b84a90cbcfa62a045d726df71b6bda0eeca0be":"11111111aaaaaaaa11111111bbbbbbbb11111111cccccccc11111111dddddddd22222222aaaaaaaa22222222bbbbbbbb22222222cccccccc22222222dddddddd33333333aaaaaaaa33333333bbbbbbbb33333333cccccccc33333333dddddddd44444444aaaaaaaa44444444bbbbbbbb44444444cccccccc44444444dddddddd55555555aaaaaaaa55555555bbbbbbbb55555555cccccccc55555555dddddddd":0
+
+ARIA Selftest
+aria_selftest:
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..95dfd8a
--- /dev/null
+++ b/tests/suites/test_suite_chachapoly.function
@@ -0,0 +1,347 @@
+/* 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_encrypt_and_tag( &ctx,
+                                      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_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_setkey( &ctx, NULL )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_encrypt_and_tag( NULL,
+                                      0, nonce,
+                                      aad, 0,
+                                      input, output, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_encrypt_and_tag( &ctx,
+                                      0, NULL,
+                                      aad, 0,
+                                      input, output, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_encrypt_and_tag( &ctx,
+                                      0, nonce,
+                                      NULL, aad_len,
+                                      input, output, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_encrypt_and_tag( &ctx,
+                                      input_len, nonce,
+                                      aad, 0,
+                                      NULL, output, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_encrypt_and_tag( &ctx,
+                                      input_len, nonce,
+                                      aad, 0,
+                                      input, NULL, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_encrypt_and_tag( &ctx,
+                                      0, nonce,
+                                      aad, 0,
+                                      input, output, NULL )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( NULL,
+                                           0, nonce,
+                                           aad, 0,
+                                           mac, input, output )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           0, NULL,
+                                           aad, 0,
+                                           mac, input, output )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           0, nonce,
+                                           NULL, aad_len,
+                                           mac, input, output )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           0, nonce,
+                                           aad, 0,
+                                           NULL, input, output )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           input_len, nonce,
+                                           aad, 0,
+                                           mac, NULL, output )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_auth_decrypt( &ctx,
+                                           input_len, nonce,
+                                           aad, 0,
+                                           mac, input, NULL )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_encrypt_and_tag( &ctx,
+                                      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_encrypt_and_tag( &ctx,
+                                      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_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_starts( &ctx, NULL, MBEDTLS_CHACHAPOLY_ENCRYPT )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( NULL, aad, aad_len )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_update_aad( &ctx, NULL, aad_len )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_update( NULL, input_len, input, output )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, NULL, output )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_update( &ctx, input_len, input, NULL )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+
+    TEST_ASSERT( mbedtls_chachapoly_finish( NULL, mac )
+                 == MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_chachapoly_finish( &ctx, NULL )
+                 == MBEDTLS_ERR_POLY1305_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.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 9899289..52526a8 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_dhm.data b/tests/suites/test_suite_dhm.data
index e351ebd..734fd97 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -19,10 +19,10 @@
 Diffie-Hellman zero modulus
 dhm_do_dhm:10:"0":10:"5":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
 
-Diffie-Hallman load parameters from file
+Diffie-Hellman load parameters from file
 dhm_file:"data_files/dhparams.pem":"9e35f430443a09904f3a39a979797d070df53378e79c2438bef4e761f3c714553328589b041c809be1d6c6b5f1fc9f47d3a25443188253a992a56818b37ba9de5a40d362e56eff0be5417474c125c199272c8fe41dea733df6f662c92ae76556e755d10c64e6a50968f67fc6ea73d0dca8569be2ba204e23580d8bca2f4975b3":"02":128
 
-Diffie-Hallman load parameters from file
+Diffie-Hellman load parameters from file
 dhm_file:"data_files/dh.optlen.pem":"b3126aeaf47153c7d67f403030b292b5bd5a6c9eae1c137af34087fce2a36a578d70c5c560ad2bdb924c4a4dbee20a1671be7103ce87defa76908936803dbeca60c33e1289c1a03ac2c6c4e49405e5902fa0596a1cbaa895cc402d5213ed4a5f1f5ba8b5e1ed3da951a4c475afeb0ca660b7368c38c8e809f382d96ae19e60dc984e61cb42b5dfd723322acf327f9e413cda6400c15c5b2ea1fa34405d83982fba40e6d852da3d91019bf23511314254dc211a90833e5b1798ee52a78198c555644729ad92f060367c74ded37704adfc273a4a33fec821bd2ebd3bc051730e97a4dd14d2b766062592f5eec09d16bb50efebf2cc00dd3e0e3418e60ec84870f7":"800abfe7dc667aa17bcd7c04614bc221a65482ccc04b604602b0e131908a938ea11b48dc515dab7abcbb1e0c7fd66511edc0d86551b7632496e03df94357e1c4ea07a7ce1e381a2fcafdff5f5bf00df828806020e875c00926e4d011f88477a1b01927d73813cad4847c6396b9244621be2b00b63c659253318413443cd244215cd7fd4cbe796e82c6cf70f89cc0c528fb8e344809b31876e7ef739d5160d095c9684188b0c8755c7a468d47f56d6db9ea012924ecb0556fb71312a8d7c93bb2898ea08ee54eeb594548285f06a973cbbe2a0cb02e90f323fe045521f34c68354a6d3e95dbfff1eb64692edc0a44f3d3e408d0e479a541e779a6054259e2d854":256
 
 Diffie-Hellman selftest
diff --git a/tests/suites/test_suite_nist_kw.data b/tests/suites/test_suite_nist_kw.data
new file mode 100644
index 0000000..eee4574
--- /dev/null
+++ b/tests/suites/test_suite_nist_kw.data
@@ -0,0 +1,462 @@
+NIST KW self test
+mbedtls_nist_kw_self_test:
+
+NIST KW mix contexts and modes
+mbedtls_nist_kw_mix_contexts:
+
+NIST KW init #1 wrapping AES-128: OK
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_setkey:MBEDTLS_CIPHER_ID_AES:128:1:0
+
+NIST KW init #2 unwrapping AES-128: OK
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_setkey:MBEDTLS_CIPHER_ID_AES:128:1:0
+
+NIST KW init #3 CAMELLIA-256: unsupported cipher
+depends_on:MBEDTLS_CAMELLIA_C
+mbedtls_nist_kw_setkey:MBEDTLS_CIPHER_ID_CAMELLIA:256:0:MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE
+
+NIST KW init #4 AES-224: bad key size
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_setkey:MBEDTLS_CIPHER_ID_AES:224:1:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW init #5 BLOWFISH-128: bad cipher
+depends_on:MBEDTLS_BLOWFISH_C
+mbedtls_nist_kw_setkey:MBEDTLS_CIPHER_ID_BLOWFISH:128:0:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #1 KW plaintext OK (2 to 2^54 - 1 semiblocks)
+nist_kw_plaintext_lengths:16:24:MBEDTLS_KW_MODE_KW:0
+
+NIST KW lengths #2 KWP plaintext OK (1 to 2^32 - 1 octets)
+nist_kw_plaintext_lengths:5:16:MBEDTLS_KW_MODE_KWP:0
+
+NIST KW lengths #3 KW ciphertext OK (3 to 2^54 semiblocks)
+nist_kw_ciphertext_lengths:32:24:MBEDTLS_KW_MODE_KW:0
+
+NIST KW lengths #4 KWP ciphertext OK (2 to 2^29 semiblocks)
+nist_kw_ciphertext_lengths:24:16:MBEDTLS_KW_MODE_KWP:0
+
+NIST KW lengths #5 KW plaintext too short (2 to 2^54 - 1 semiblocks)
+nist_kw_plaintext_lengths:5:13:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #6 KWP plaintext too short (1 to 2^32 - 1 octets)
+nist_kw_plaintext_lengths:0:8:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #8 KW ciphertext too short (3 to 2^54 semiblocks)
+nist_kw_ciphertext_lengths:16:8:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #9 KWP ciphertext too short (2 to 2^29 semiblocks)
+nist_kw_ciphertext_lengths:8:8:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #10 KW plaintext not a multiple of semiblocks.
+nist_kw_plaintext_lengths:21:29:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #11 KW ciphertext not a multiple of semiblocks.
+nist_kw_ciphertext_lengths:34:26:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #12 KWP ciphertext not a multiple of semiblocks.
+nist_kw_ciphertext_lengths:30:22:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #13 KW wrapping output buffer too short
+nist_kw_plaintext_lengths:16:16:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #14 KWP wrapping output buffer too short
+nist_kw_plaintext_lengths:5:10:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #15 KW unwrapping output buffer too short
+nist_kw_ciphertext_lengths:32:16:MBEDTLS_KW_MODE_KW:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW lengths #16 KWP unwrapping output buffer too short
+nist_kw_ciphertext_lengths:24:12:MBEDTLS_KW_MODE_KWP:MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+
+NIST KW wrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 128 count 7
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"095e293f31e317ba6861114b95c90792":"64349d506ae85ecd84459c7a5c423f55":"97de4425572274bd7fb2d6688d5afd4454d992348d42a643"
+
+NIST KW wrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 256 count 11
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"ca8f6c56a9c9300549e9eae75a4604b8":"1542b8662136245162c64d45af1a982302f69f1d01a1a6bc29ef8facafbeaea0":"4d340c10bbbddf5b2014ded264bffce49901bd22adaee074b0f25a2d19c134eb3c7f38c5d0444766"
+
+NIST KW wrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 192 count 8
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"b4902b13ea73f17829b4e334fb359ec4":"2073399c7794c8b73dd782dc250dab31c80a8cba33477ab2":"37eda4eec3096135f5193c37bdeaf498b71e3a205c5638682fe746f236566b11"
+
+NIST KW wrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 320 count 14
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"579448a3d638f093742ae6b24d729849":"464d3162469899955d8bc8bfc0a22555bce609b2415bedf17a942abfe96ad4e124d4a832fbcff49f":"dadd1440a06946eabddf18e784b7719d36caa33cb626aa03aca057585584ea07a8714ecb90ceb232d6b0760845105fbb"
+
+NIST KW wrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"98311985c4661d7e811ee56070e6fecf":"18840c96813864ef3093b48cdde6ac5d78248b96d4a2cd1f15f0b56f98213dbf87e1ccad04e0d4f1954c233ea3e48fdad8f2b1156e54e19e3b5f4a66d2e9149032b876c51249165fe8c28e112a685b2d228a8ac308017574274af36a4ea3877bcc9850bafe8fc0e0a712faca0dea98396f9143bc5819fe4933a806e9b965133e3c695a45f0fbd6961798c400d7477287df64798b651e0d3009c13f7a2246c28f983509b9e5339919f2cdffcdfc550693cba9491c00334c4a62d878c4d0ca57b1104bc0174968ea8e3730b9e68db49678b23cd508ebe3e12e94b0ad3791023a8ef95473f0b32f906738f34e94e45a4480ad768072e1853adb63996b9ac27a1dade70804b82290a2274c6dcc3ccd40a8b38a56a5eb03f59075de015e8f9096f53549f6374e02da947fb849287a447f757cc340b6bded71d480988b6d2fcd984fba841470519830304667fef0a577b4cf84f76aef9deb84dde36abfbd76673c17113dbea7a3e24bf9b57a8fd17173a1ef91497b732b3fa8889bed58a503a0d3e20bc27ec4dbf5d13a93cbad05495e3df15e1fe34a3a6d6f648ea4aa60b2f114f30944ae593675dac2db188f90a3c483fb82cec0f0d295544d798b62cdcb51c6c036af1a341d78babf87b92609c1d866e311a46abccc8ba8c6a41420359bb061d7e752c0ed25990eef57c9f9e190572203f8c473edf8cfc8c26d34e37240f45ded97":"625aea9122b7b57b9f36446f9053acc42c6435a7f69d91b41547026f833291d488e477c7ccba698c143633a304f463d6af4a3e72c189234fcfc360013e65b07b7f7a36c529d3fdbbdbd6224bf100c14bc5354893b44790f54c739a2b1f5bda82d70fb600ed9b0606dbddea52e508b492b72d8779856274aaaaddc0a3edb6cfc788b603101bedfcc3f44baa62336bd950c2e349d5daf04f2e23ec2628893d214e277569c565e5e6aa8b72ffa14118a3b57f814b4deb179980b5eeefa4fd93f1751850466e929be537801babc2120f3ff1ffe5fea813ec7788eaf43f5ef657e5af48395c3ad11aaf741549090b58670695f7c95c68e00576ca18ef0313f2b4b757219fc8db3dc2db28721d6f912547ebfebcd96935c3100aa4e4df9955acae1b4e2c10df1166d46c4285ab631c6d2ce58ad3ae99c07c019dcd15958694055281ccd6f803af290431f188cc4c429e84a4c30fd9c63968dfd0951c417efb71921c207de172a9546bdd3e2bb35b45e140892c649f88c31a438f864e801a69f8010aa3d77a26601a7a89067c81b0f7e70d8e82f21f88c7d0bb0c8ca0db875d6c3f8c6f6d709bbb31c7da2e31f3571daa2c5ab13bfc16624cf35abd526e84269fb45bbd2fcd8c383d6fbb700bc4b5205b3ef8c4323dc0d9e0370e56a3d1e5e76aa4de082e4c2a0afd092845bd5dab52a45943181461b76e3984b95f48bea80a94944241d04b5634c86274e7"
+
+NIST KW wrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 128 count 7
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"13df8fa68a6e096b9b5bbaebb64ace2e6a05485b5cb7e43f":"3ee9367f631fb375ba47241966ad4ab8":"d0309b1291a06c595fcaa6dcf97817dbd7b7ad2cf48ddec2"
+
+NIST KW wrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 256 count 11
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"17c25023ac76a8af777a6f71c0c0f97931554b0a15a79222":"15227ef52412346e83a18c54a75374f69a24de6a07cfba9082596eeb5d758bb0":"0f8e2fe4f3a28c1fcebf20fef2bfd3489deb284e03d057337496285f4ffe62f074bafa0a0a6e44e4"
+
+NIST KW wrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 192 count 8
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"49d1c4ec51f2695ad7e47554efd24170ab03f628eba7d5fb":"8bf961097a6fa75694cf0ea47cfda23928fc433d5fc762e6":"dc72c58faca0dd662e5fefd05cd714987cc2470219db77baf779fca865f31529"
+
+NIST KW wrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 320 count 14
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"e06ebf0145b178ea45687abe366fdec559877dbc9300a653":"f0104e9546628d801c4f7e875f1ca4f385e915b0c7bd52ed158b6b42d7301f1df6dd5bfc80d0318a":"5b4b1d4ef349fcf5eb7d720d84b2e79fbabf3db18277ada0752b9883c21f0e24281854420e6751af8fbcc4b98be0c1d7"
+
+NIST KW wrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"932ed6ee1db1c4cf7fd81efce5609641cb5f3409563089dc":"da8dd9c1dc8cbf95b0fa280747c1007ecb086b7c944b0db4dfa3bdf6ed0c9725901cb838c2e30131250188c22bd92b068aa0871ce58a0c22307671612fc4884a655329851d54afd48a9d3a7f97976850d6fd842034548aee67df1272b06f155eb21966858731c3c35d4bb94a1ea351ef5a8c4779c077d648ec1c4f27cfaa48f47541a8f36831e35a961b076307bea928e1856e448d7695a0f7fbcd8c82800d12f530c2086f3b67bc5081d384010b47d327120def5c92f815aaae31d32893cdd18a71ba4e208445ff3a2f68a0a46689458b0f2d6d9cd3726284e56b4c020b97a82d4463f74098cfd7bd7a5f12157a0bc812266b8f2c215933cb67518f900602f0825538e05765318b6d31150007e410b92d5d957e119c5d94aadba193cf6da230387b1c5e6448515f9789a8867571ea82ad34dc5b912d6cd243bd4fc2f19d132bd8f1f5cef00a141e30ec4d3f7a546a215d5b0c7e70c3b0ec4fc34b66c4170bf403ef910dd3897caef33405827a55f943904c4e1b1aee4cc3ffd0ad27e316c164e2b5bbcf73df60d8859201b6602be01ba638aff468f3136120c117ca848ae161ecafade668e2d04b227437d4b91c6fc40ebd9490f211bcd21fd7005d200ef584f37aa2c4c769174551cec0d7f2936ae78f6c389382212703d0e7c82aef1a736056ed9c45e71439731537a2edb8a63741825c678a11c42e5b2281b43e203b0523":"76b6772984932bb6314d1eab8f625e044920f9494789e9a0ac2affd9a209cabb72ee83331a30472934e02ef28697d541a071eff9eb5c7dd49862f11384d46e8f4c2ddb084e76ef382117a285993e4a9f89e1e0ba6612f63b3c8a54784f940d7e6baf12cb67d27038e91d1ad4feceb5bc44daf7444f76fd140ec7a94869b4f99b9fcf6dd68e78c6a0a4794d55a1c91756ceb9d28b43d9c72b26fafc25c71e63dc175b29282d4a70813b833c35354983f29796909a9ba515cc5c37c58e95aa6f35b850500ea933b27a5922188c2da64680362602d71d169f853af0564b53bc613c15772ed82f89c2f8625670179a83536972332509e7ae4e0726271c5381501d3d88a3cc34a56d80e3e553b9b595e358615e92f361d695837734cdaddd7068c441b310aa511407b53806f1fed984a73862ea2ded1ee67d14feb5d8661ed94a62f5768829d6feea30db392bf24f0ea103fd2a60acf1fcd4bb2465641712113375bc2c8d73650795689f9061608b65e0e608f9948f5efcc0fba62c50b8cd97f67df2b0eec4f5a0cd354e982ae6a62070f4127b6556714bb2267d558112638f10c78be201ba165e57ac9cab6f3e35a762b7fe83b3c7c050b77174a4bf14eb2cac4d6d58a94f0c02727ad020a6a05d9ed145151d4f1ed41d5a6d06c50c0e1d5c24d09100d4f06c50d06a332a95845f4192ef577dc484e7acb91f0b2a57c1f8bef97c23294c59099eea13b3"
+
+NIST KW wrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 128 count 7
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"e823c6ef53b110eeb3f178871cf436887cca9df061d1f26409ec3b410033d967":"f90c279e9e6423804a6505e8effd924c":"0abb50b222af66058646156d106df7c85c28b708395eb9dd"
+
+NIST KW wrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 256 count 11
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"e5cca71056548467bc9c2849aba67cfe0fd74c44d514535d2314022a3f3e6ec8":"326b6da4dce95c94226b63c2d38c4e005c566191b00028b59cc788e0af5261cc":"2a4f331f451589fd103d9a9cbbeae5d5f5be7acf15aa6e21c45e09362263cf34b0ccab7c8a28dfed"
+
+NIST KW wrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 192 count 8
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"6a077f95496aba1bb80831280e7563f3a187e6d014342028349f766b791108ce":"a77b3ddac0e78c9176b7445f9ec349b2d85aa2f57e6cb362":"7c065be0a2173e0f14a3418779e7f3eb6eb7fbb7a3c20fd6c08b37d408bd9423"
+
+NIST KW wrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 320 count 14
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"752b21422647f1006de116360e88e2f6601eeb5aafd27cba56c20193fc1b941a":"a5948c20bc611187d688cb03caa04fb17774aa4f99ae3da5d821bcccfae950d72ca74b3a870008aa":"d71109224edc4233db8819aaca4db9c61ab5aad2806d0e985f1830acd8adde23ce75046b2057e0a23dec7a053bac6c4c"
+
+NIST KW wrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"931bf2c55eac657ae56fc0a9505a6ea7cc9af5162d844ccf01f19debfad09cbe":"aa8074a195abd88930825b947cbf3cca9810eb829d2e7a09f9e9cb1f8271986d00c5be478150fbbe990de8c61af879495274a60d83f98cfecb2473a35d86fba6ce839d259ede318a362e7abc1f8a18168606d5e680f456f1ca19942e67e5aee382536df7c28204b7842b99023336b735a861cf28363e7773d7b0bcf32b5fab14cb524249863fd7ce49a7a7882b53728f7ecd020393852494df09d9a69189ea713e730e002252af18864b948a642d7c0fb17b0cd5671f14ae340fb0e83b4bda920445927b8de8a82ac93158edbbd57fddcc1d908688770a07c27d2bdb7151d986e85cdf1606b0c1c959542e75090d8fdce9c2a9c162e6fd988746c9bc916ff3f20f054690173d143212b74c5a8961cd46663958744ca1334f6c1dfc13fa83c0a9cc229a1030c6c84d01751ffef54d0f9edb2a4851a187d02f097a5c716f8fbae29eae76738239516ed08c14f24f9378451e9e696742a4bcdd9e0ecba49fd05eb93698afaa1b0d5558521c7b4e77b15ca2612619bbd78f670a1562a9a0a0215fe64211115e60476525444b351a4f8ff5551dd198655423f3fcfb5967c4f77e25d3911504de1d034176d3ccecaeb31bd29677c7569c858ea24d7017ce0b31f1911f4fa14b2afa429c06115bc285ea8b90bbedbcc63f5f0829dddcb17e8f9d21bd71501679e514147e1957ccf986e7e96a0e63ded70a9d017162658a901f55b1001d":"6b75fa8070291ef7c89f5cc2060c56270f5077a6df65a8095cc76b717167e67af70dcce96de4aa32293c17d0812f666e1f42e7e662cef7a3148486d2be7f314631ed6606f326e9781c3ed6be1735bef8cd5d3ac7d2b45c4419ea61462baccc0ff87b83b9b6cc85278c0b20bc15e6baa0a15eedd9e99df82c8e61476529c98aebbc9d40d417f9af26e6da5d115acdd6007d83206c616a39fbe21c6331cc45af11c578532a7cac50aaba21f3cf317534564c2ee093ef127484aea62c7a90327fe9bbe8e45627974306d8cc7452e96033f0c8c30ba2d7fb644796a49c9b502d3db7d4995f920fe21962fd2b634c15be0d82e9cf0ae3fd2b6d45524e1003ab9788ee56cff3e2e62c5784061a5ff586b5907098b8ab54bb70fbc6cb066b071fedce10e013014d82162e3cc6f9be3b4067555907a4df55012a9b1001888c55dd94b4f8528bb29e7985ecb8a7958fc8559831db05002479b1f39e5de3659f3a6e8289d9b8ff4eaa3f864b1ea101d84b4c6138aa6ffb95dea4f825d23f5d368727ca0a8cacb74f7bfd70fccbc951db99f2f4a580425c31a8552fa27397cf8b7f420f13fdcddca553a5f31d8645615b98a88795fb4472bc7cd6e8e54707d7be1f3dd7d4871725f6bc0e65762f1e42e22c411fee6dfd8139068798c7ae9781c8e5bcf4732a83f9142edce36e1ee6e20142adf46c5abaea0ca78f61e16b6875927d4141f6b215da1f48748bd33c"
+
+NIST KWP wrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 8 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"d060e5faa705b6c600ecfcd5252bbfba":"3d":"28ccc6da03cd79b78c7207946fcee402"
+
+NIST KWP wrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 64 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"663ee3d40628059fe01a9766d5c1c31f":"1c6ccd67438f20de":"c2717ed6e51bb4314388cd26464f4d18"
+
+NIST KWP wrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 72 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"7865e20f3c21659ab4690b629cdf3cc4":"bd6843d420378dc896":"41eca956d4aa047eb5cf4efe659661e74db6f8c564e23500"
+
+NIST KWP wrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 248 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"02a92285d0baa874ac94f6648988d44f":"6ac78aff505805e3145fac44eaeb6ac92945ca12d9bc0b6fee8b1e5b983f37":"18b251cf54d2a51ac903af2fd008f6aa2b1bf491fa2e0458dba272866821e98ad037eae4af654811"
+
+NIST KWP wrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"6b8ba9cc9b31068ba175abfcc60c1338":"8af887c58dfbc38ee0423eefcc0e032dcc79dd116638ca65ad75dca2a2459f13934dbe61a62cb26d8bbddbabf9bf52bbe137ef1d3e30eacf0fe456ec808d6798dc29fe54fa1f784aa3c11cf39405009581d3f1d596843813a6685e503fac8535e0c06ecca8561b6a1f22c578eefb691912be2e1667946101ae8c3501e6c66eb17e14f2608c9ce6fbab4a1597ed49ccb3930b1060f98c97d8dc4ce81e35279c4d30d1bf86c9b919a3ce4f0109e77929e58c4c3aeb5de1ec5e0afa38ae896df9121c72c255141f2f5c9a51be5072547cf8a3b067404e62f9615a02479cf8c202e7feb2e258314e0ebe62878a5c4ecd4e9df7dab2e1fa9a7b532c2169acedb7998d5cd8a7118848ce7ee9fb2f68e28c2b279ddc064db70ad73c6dbe10c5e1c56a709c1407f93a727cce1075103a4009ae2f7731b7d71756eee119b828ef4ed61eff164935532a94fa8fe62dc2e22cf20f168ae65f4b6785286c253f365f29453a479dc2824b8bdabd962da3b76ae9c8a720155e158fe389c8cc7fa6ad522c951b5c236bf964b5b1bfb098a39835759b95404b72b17f7dbcda936177ae059269f41ecdac81a49f5bbfd2e801392a043ef06873550a67fcbc039f0b5d30ce490baa979dbbaf9e53d45d7e2dff26b2f7e6628ded694217a39f454b288e7906b79faf4a407a7d207646f93096a157f0d1dca05a7f92e318fc1ff62ce2de7f129b187053":"aea19443d7f8ad7d4501c1ecadc6b5e3f1c23c29eca608905f9cabdd46e34a55e1f7ac8308e75c903675982bda99173a2ba57d2ccf2e01a02589f89dfd4b3c7fd229ec91c9d0c46ea5dee3c048cd4611bfeadc9bf26daa1e02cb72e222cf3dab120dd1e8c2dd9bd58bbefa5d14526abd1e8d2170a6ba8283c243ec2fd5ef07030b1ef5f69f9620e4b17a3639341005887b9ffc793533594703e5dcae67bd0ce7a3c98ca65815a4d067f27e6e66d6636cebb789732566a52ac3970e14c37310dc2fcee0e739a16291029fd2b4d534e30445474b26711a8b3e1ee3cc88b09e8b1745b6cc0f067624ecb232db750b01fe5457fdea77b251b10fe95d3eeedb083bdf109c41dba26cc9654f787bf95735ff07070b175cea8b62302e6087b91a0415474605691099f1a9e2b626c4b3bb7aeb8ead9922bc3617cb427c669b88be5f98aea7edb8b0063bec80af4c081f89778d7c7242ddae88e8d3aff1f80e575e1aab4a5d115bc27636fd14d19bc59433f697635ecd870d17e7f5b004dee4001cddc34ab6e377eeb3fb08e9476970765105d93e4558fe3d4fc6fe053aab9c6cf032f1116e70c2d65f7c8cdeb6ad63ac4291f93d467ebbb29ead265c05ac684d20a6bef09b71830f717e08bcb4f9d3773bec928f66eeb64dc451e958e357ebbfef5a342df28707ac4b8e3e8c854e8d691cb92e87c0d57558e44cd754424865c229c9e1abb28e003b6819400b"
+
+NIST KWP wrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 8 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"959b4595778d7b860e08fcb5e24b11f118fd5d67089f2ea4":"65":"1cf986a0fb2208977c37a4c3830eba72"
+
+NIST KWP wrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 64 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"02dfb6662e0c1b95d34aaba7eb6c1fdd41c52b89213d5b18":"27361c34c2601fe6":"089f835f3210734aa1a2282c6ff30ef9"
+
+NIST KWP wrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 72 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"9464f1af6aabad076661328bcfd15777da16a288a2660009":"431527c3a644c106bb":"d9b257b400d808a0b0386af3be9154fc7f2fb2d7edc06201"
+
+NIST KWP wrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 248 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"df419ca84650ef28a1c5d1cb47917e4480a3aca4bd29dd5e":"3d84df372bc0b854c058441e952738ec79474b673c94e32dc78d23745fb5e7":"497e966414475938204c3b3d606d5160461c54dfdfe903b6624208d7cfc90bb403f384bfd54d1ed2"
+
+NIST KWP wrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"a85b4359ebd240012ec749459bc928eaa52c84e887ababb9":"9db71e2a2d40f6fcc1b8311167ae13fb101bdf7b5c4e078373c0c3cb3f3a3ca39a91a6985d3fdd48d93f2b5a09b2a69350da2846ce6a37d018dda95ddac93a92fda7b7c3bb6518dd78f367f70e34e0bf19dbba46fd13d3f3e0a1776350f27138c64b177aa39c54dc06184b320016b6305c2dea19fa6da634cd613d5a4f71bc045f555a1ccee39b8f1ab90840b5bae555932e08719bf38f72bc1057875e8c077a70629f46be91281b977ed6f2a71171a7cbaf8e0566e55da6220a85a7655758de3b372144ef76d0337d3133004c0db096b2c41f524f95706247a331d08a6ff72b425395fee8e1ad308ccfe5b0525c40803e529db72063731fe1644891bdc0d5961397006e1f5d6521ad4e5aee3544da101fd3cf6bcf879220a612b7016e5eefe7369f136086e8f5109ae83e8687519f2008406d20992b64ba1d27b436ea5db1fd734340f3b2279e026a96e3f9c5c7b99553e35ada9e1d7d708a73774718f9b7073c0889a298f212d47ff5960e04743070338f99b11687396da2120b8f132535c0911b04505c0e6c32590c82bf59486fadfbdc0f16a224b2f52082eb66201f041d64b34809e5e91cda89d80d78fe1e15862bcf84f65a301ae68d097c9be09f3411c11cf83225733dbc9306ad2630eb7994a0d112ba83dc542966414137fd008fbb7995f649edf844fe5ee86b94acade1a04f42dae21928b9b0cdde8cc66095772d":"72880f9f173f0ef4d99e3ae71f6f3b94f66a08aaa22be1d206faf431718c1a29bd0a574b1a28b69f0e64d56d3e43617dc73506a939b7de9005ef0ee3f02b9265e91a32aaec58b7ab990f39774f6769c9be9ced3339f6bf0159055abe237c4c755613a6c03271abea3bc89527f284a3e1557ae26b3910b779a77a128e773d11d7d641479d02f4888c989cbb8d928da0136b965531730a3c0c32404351f4c2390d996dff58985ed1d4f4021a5d6ccedf4555066a826a04055cdf8c9c44bdae26619390b3e22b064f86b28382094a3e299d55ab335ade601699e85f19d6f6f12407caf84ad47f03d75198691f1a9b2aa9ed95e508d8551b19601418922f3289fc1efc3abb1ebc2f4886dfe325cddfe25dd908e5aef8ad197ce2703e692b9c46a12201fa71ebc2e323ff8926ecc059ffeeacc0446d3f28496f17f1b4ad6504e4e24188862e25f3dfc36adc7f79920d88e6c53269cc4e5dbbebbba1a2347154683c840d178476ae11d6ce574c26b8b895957b8623807e8831b87b5639aeb415adf1bbef394046deb3bbe91a5c17f2f67131ae5f696352a488e3bed40df025e0a0846e0037847350fe8ae3cf73141d0ec550d82b89c05bbff7337bfe846411d3f0bd012e4de2fe5b83c7210214c0404b40e08abdd3f4bc441f9b6e1efdaa4ac13b85d139f670a6060a1ba8d2528bcd19f241d9ee5077d20c120f2b484c67c9c598b1b209824c3b8aec2b7b"
+
+NIST KWP wrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 8 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"0070492ff3aaa190496c72bb0affdb6fac7fa9cb32e6e91a46ea34863422f807":"39":"643a9706af6bd06410b70ee38f546bc2"
+
+NIST KWP wrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 64 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"c6e882f5b8e361e43bb3e54d5a7b8c690f485bcbec2dd2183c7e623f6b02c5fc":"99ae80eec64630ed":"de0680b34f7374539ad9b75f08f4d8e6"
+
+NIST KWP wrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 72 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"70da43aac823c6dd37d1109f5b18feb4503c973288989745e2cc1cc21d9570c6":"edf17d966ed896aee3":"d67b5b2ad15c645450e23b5e7b6d682f8ae20e716d470db7"
+
+NIST KWP wrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 248 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"e941febe4b683c02dce56194a86b72d4c569e1fc84bc7a6f24c3ae2b39bf5440":"c168cf12acb6679c24d424baa62ed56559caee163a4efa946478ad43d7dbd6":"4ad9979caa72fddff0876c0295a57fcf74e5980fec2cf622191ec6b5aebb75e0adebb12d0862ffae"
+
+NIST KWP wrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"20f31cded60b8ed8d9d3fd1e1fa6244e76c7cb7628bfd28a5d63ce8aa2c9494d":"f07225202842c8dede42215301e44b9bb7e625d3812f74f9b6ddbcd024ebd1f33e2cbf280b9004941f3cbf86c880a2357f88f92a6dcf8dad9da7dddcd00f3635efdff0af4382024e93c2af66b991e565eacca6b886f07178c9b4adad6f0d6ada5ff6aa7cd0712519a947a8089cea5e1e3e40ffe1806010b0149f9ffc7c4dd3c31b3d08d5ae1997c52369393d58611dff9bec501c1ab35e6ed3e7f9445a34e211010a8236686f154e0a5ae3433d6a844eb3884961aa6592216d93952b46bb58a4195aa80966ad0ccd4a7e23823912556a90d5ee9c3bb952ecbb9d895dabd3b11ab4f2e3a6c2582de50403289230ef4dc46e7c0d870a3f0cba9d643a0349503c1b162ddb6350e699589eb47bd563999f55a1adb6b78b52f006901b0427ea7d3394bb0adae4637b4f1ad5d5425e2c8ff3083506d7ad7ba4c7405a778b0a3a11760c96900a5256956cc9710091d073a19f46a985d004651fe2b6448ed761bf9bc81619cf273a6783d868d090753bf01318be21afd88d9f3a961a69f93e9d9fb822c80acc7b48cf14a08b5b7ef15c66975721b7cde9761a145b679155472a44dea8fedc0f86ae7ebf6283ecfde5f2444b51569e6723a7a19e28cdf8dec6791ccc14af95abad018f741575b343cb1a20a2a9adf4248f99728069a1e2e78ad8966c41c9918fb7019ef56c153a183a6247d22d9956564bb03075cbfd1b43d96818b28484":"a5b63618fc0c4512960f00a1f226d9837a90480baea75265453b9553b12a58c72153080842d7f8710f317f88fbbbf97caf879ab4bf416ba767ee9aeb34357f4a2d0e8b9571054d98e28804a70bc4d74807f2bfd95ee955bfdbb6f4d6969a0c3c3b541a514647d5cd8c9740ac3496095c3f145c50c97ec98b935158fbdf89705d5330015e48ece89188b8c1bcb2ad6825d865b375a9b9056b743dac720feeac033c9f757f6fe73dd7c4a747661b64cf490a0dd43b547cd791a5d78dac97efcd355f7ebac248fa2a33e4fad640dc34e0d40b0d36588aa32f0864c9446739a6b44ff84666d723bd7d646c5172cda932fec34ddaaba342b02a9604087ef042a2be4774194b5d32cb3fb112438fbf2801050b5424635fa2d3d3fb10332965c73e6669e65195310a3a30602640e9809179cdfc50de585aa1c0072423c626815d281a06eac3b6ffa137716318e288e3f9970e415ef0451bdc557968febf9eb6772c1f77cb8e95701246d9c567048142bb25e340351b87d7391822d9ee7fe51378bc0d08135f9f39cf44b348b87937939dc61f430dfe308cada632722e23aed5a0699e039cf0563ab8025163744b136a13ce3c62c748c89f5e17540f105e7c6ec9ba13515b504342f9e6dc7d65b9a633d8c0b5c9fa858dbb9b3a594406d478a81bb9abfa289730408c1e303c663a61d5caca00f615065312580042862397b9aa8c80ca812887664c439c8c68"
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 128 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"e63c2cb1a2c1282d473b66753494a591":"084532f86949dfb7be2cdf09d2b7505418e7bca5185661e1":"a26e8ee007ab90f599a1bc31cdabd5fe":0
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 256 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"83da6e02404d5abfd47d15da591840e2":"3f4cbf3a98029243da87a756b3c52553f91366f4ff4b103b2c73e68aa8ca81f01ebda35d718741ac":"67dfd627346ebd217849a5ba5bca6e9ce07a7747bed1ba119ec01503202a075a":0
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 192 count 7
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"e5c2fc20f9263da4f15b817874dd987d":"0538fdca42f1fd72afadbe689fa8a396996d734e4f082c8c4ef41ef11dc6246e":"35a261169f240dffe4701ce41f6dff986764afa6e84f63c9":0
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 320 count 8
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"3f5501341f617cae30dd0afbfa247c09":"72fcc9e5942344d11c3b23503b170e39cd635da3a83aa9ffb196cfb1d6eeae6dc5f5683238da6e9b49edbf95819bbbdf":"e2a34da9ea2ad66e130251f8a7798b87d7bd7601abc5ae8f7305b024ddb4b3e00351484165e16d25":0
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"adf44a10a05e64f2df87db52f3ae18d3":"a940cfea67b90c81b4ccd793f186dd7c6a3c0ff5a6feb5bbef99eaae2b14a979f1acee92b5e4cd750f40571804d380f470e1f5201a389476f97bf29f6699053f468bf102975895f4c1a679a46cf627b22c8d956679ce53775702899afa223c87621f859dccb876d317f2a486d0a4d4ad6ab7e2d9ebf7a956c394ffcff423377e21b274f8ca3a379273dc8de738c97bfd318871330abfe2539a49d4f03d0eef65856c01ebd426f2e76fab90466acbed8c4c9dc09898929d80244eed4fd51e7eff567c2b340e928f298ec00cc8839e1ce9ccdff40a7edd04e01440f2288c384c673de8a758ba50f6f910b8002e0786d2eb633da0ef7eff025f37b45f7c9b918863a56e2da1f3fcd12b990f959051289a1113054c38c135336f19672c86a51200763678cc4ef50ed290d96fec4afaa53af165aa7ebc11d787ab1c535a0abd00b477b914855759477df2afd516a85a66f8b91fb5f5e98232e601e249b3faa856bc6b26f1945f48542601bb4ff1c0dc46f44ae023c0a33ec9faa7467b1cdf1c08df7d00b800ef28e2f77f1e6941db9ce8e71fcf82a14cc8983614e2ce3cb4b3e976a8dec76e4309492ca68486d119cd566b9692d1a513ff30675737d1777a3a1a95b6588685b5a64d890cb8f79578fae8f1d22b83747bf876da582e56e5267ee8e734e0fa9271f5455c40fd599082c0acb442927643aeefffa5bca0a88c38671db14899adbb4819dd1e2d":"a2b43c25c5f530a6a29c5314319bee95e0ad5a630aa8dd614b3751205118e35117c31de7d1ac41f9d782ae8456ef0387cff49eecfbcedf2d9c0b18182f5e043e3202c527be77e6f0404a9746ea1b18978a916cd47d40093813a3b0ba1cb22280fd7f00a7fb4f8def6a0cc1ef848a45106fc389e0ea00652151b1e61dff2cf2be83fccfbccd4fdce86f19859ac927a3dd08645cf072c3525624b3845a532e5a37d99db5cc943a0a9d42be4bc81134f314fd9e22ebd386e7a896bc2d56c933326edb18120c072579989c5bbb1991993a698f2a19387612b25a303e699d12003072fbea6e45569444107ff9a17675f5454440a6c3cc02c1ba513e26502b74a0cb6d397ff6d7d11877100fbfb5370fd882892ba09635fa3fa78d5344fa00008f488395f04a7185ec7819dbf3b165ee52b35bb4ebd10354f2d85514b2fdc1f825a4a2968ba44b3ff2812d1acc13c24ac49c22343b6080f2a7e7efafe86c6435195cb742c35d8178fe20ede0ca08278db49faeca90f95b9b17fc1ffb9d7b1d064f2266d32bbb6f3e28f3b17deeb9faa64f7c127c90241579399294eaf1dac93346943a3cadfd84d7cae1aec66877e892cfa31b5ae35eaf7c35faa6f4cd9212ef7cb2cf9df5748ed8194c380c3298734e1ccb87d0feaf49be1d275142f8421727b5a6c3415fb30ca44ab598597d136bd6d12435ae6ec3db72f6b85462878d833dfe5e6f":0
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 128 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"5d4899ee66beff1bda1fc717a1ad4c50":"bb7fd0bce778bd775e4e88d904d26a7134364c53a6c493a0":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 256 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"84bc6ce7ee4fd9db512536669d0686da":"c383db930ffd02c0073ac2cc79ec289e6866bdcc6a135a3b776aa42f14ee04f9cca06ed6c0b22901":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 192 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"266b009e911bb55f9aa0661539a6fdd5":"db9c94e7236ec56982d7ddeb9427c24580bc1fb96db98ab19340e03670045b7a":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 320 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"51c2e3d090a74bfa10db090b63ae53aa":"598a16c226e6c848a78ca30fa514edc9467f704b529c02c5522d1890b4dc21588ed6c3b070ed952adc733d865eb9d468":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-128 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 4
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"6a7814a80acae9d03eda69cad200ffe5":"e1ebfaad7f6d46cd03c50ce4e9543ff01150e9a9a69c4bc8198fc08601ed71203e39375d600f69fd762b196bf50a7dee2be55574196005c8ad53234d789a9fa6f2f0eb7d7b53c7e39a7c70e9ef93c58bcd45c0f592fbcda19b5ea9a118bc2a0d49c8cf367d4c90823eafab86165db3aaa22eee9323de7d23b7729f7f088be9db421fc8256c20e5874bd0c8348c4a6e50436fc94136e568d0aa4c29d7b65136bb378ef010db091085c9c0802466d565eace2c0bd91648fa82f8045c57cc25c46bd8c9e4060ceb00e092f7beeaece1d4f8a2a01b5b1dc9de3c7d2ada7a44d4600085b7e76929198b9823b5ae0f74c652fb8793cae7c16cf062f39136789b213d1d500d560bda89bfc0df0e6bcb07fb4a48914e1af9058b73751aa4d98ef0363e48f9d1ed42230eca1b7b24631cbad80b2d4bfbc00ad1ab797c1c459214be8f64470b4d267ab576fc1d3c86a42610b8282437dc071336c325e606c2d36de1b24595f4888cfb2ddffb46557c964a4ac53ccc1d214d44ac84b8322c93db03bdf2a04b303de4f8482b8e7ee25030aa5ad8a8bfc5dd683726a0286486356f5a965599313a2c39034774ebf646fa7ccbda35316c54d443c6da466d9c95d716016326603c3989bd7545e3506333ab3e2ad7b45b225bc43ecb37e4c301b389e06b95f09b1a10beb5fd5320234fd6d488d5691ae2e078630f9f57dd0870cd617c30bd67ac8dbf4b3a8cf61067f7":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 128 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"26045402548ee6196fc0a60208ffde21137ddb1c6c5d2ba0":"fcd55c2c60ff6de19ec3e6b13490c2821f0c565abf10be2d":"94b8276743184d086962ce6c4e63bd53":0
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 256 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"b3a0aa60fb14b658e1eb1c1a5a8e1f60307c9b9faa2f1587":"fdeda2a10e51da1817af2ba4c9f200414aec67545f5e71c608e85d14da8c5567bf51dec4ff2d8c05":"65986b3a6a3658a66cb5beb302540bb032b36c76d040b24fe278a1473ad4c32f":0
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 192 count 6
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"f0ee8ab6f804a2629e163b58c1a9e9039b53ac60493df11d":"3593dda0daead2dcf850f8670b7d0692332f57068213a772a8244d058e5634d7":"401df0c06aa4c58a71b9438e11a11a239f577b6037adf350":0
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 320 count 8
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"579e58b2bf9c34c31e8c644faef6b698131624063fb2d795":"b39acd09d9bf9daaa89304f76402065cc3d863e12df8a966f037146db9619e7be5ccbf50206773c5eca35e36492ef4b7":"9c1f66267c2083a42f3da4e754a073c1ff151681e2bc070e6e4682065fd109088a096e72024fdcb0":0
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"366af2c7a1d7a1ee5a7c239fd526024472f674ab039bba25":"36fb77bd3890aa0a4a4d6f65d671156683c48214a327e5b2b0916c0031f9f4f2c643ca721aa22e84853096bcedd7ef57ab2ae05628099bdbb55111358a06c1e99233b94a568a3f59b06d8a64332acf888cb5bd1fe8ed344937137eff629bee3ad57c73344df80b303994889bbfcd0ec08b13b687ec909cc847f383d3ba91d108c84254af4ab4c22df19897fef44b62d88b0c1b269163de9a2db56a26c4dbd0481026d27e5003153eec761f21c02f4d04898dd3ed961ab158e572aaf3b828a30eedf62a8a7b0911eff27db48ce1b7bb79b14ba43d7ecc1f87c82664c99ea857746c99a993db5807f0fb06114c00428b85ddeb9cfb698d282b1d70eb7c17d4d12575e58103ef1ed37c558d7c312f0fb1d72cbadb84561a41e4745492c8b1eea557efb9f1e9664ee995aa82e7f2a1c86dabed0b2fecd9e938c796dbf2f9b4dc269545ece94e354ca3436e4c6936b51cea7abcd2e49fa263f79757c4b5a8d18c2c6a26435fbbaf3fc759bb323ffb962bdd445dc7e5c84f9d98812e7eae254d19a06ea378b1b262daf22b634dc30aaf9d911cfff0905e5e2cfdd7dde4dbca75729bf33ef6d27d5993f19c9a3e60fccf5fa201963cea0e7caec99d79f83435d11e3a90905103c302851c8d33cef77b39c104ad4d8f45abdb111780c46784e6fd6a78e57862350a671ecbf01dd936b8dae4ce4a91d86efad8b04724d7c17a89b1d43d8abd650f88e17f5df1":"40bc409ed0ba1966e733be4b2ff9d23691e6a9f44b0abebe971a47b4ebd51bb13bcf70bc1359f6b5e670be2e6b008ce9d219abd61ad20edd97aff7458b81e6114ea6d9c85a03400477b1a32f09ac5cd1a963731246011ef4908bacdbfae5e5921cba143b9395d17386e924db6ce40361740c6ae5acfdc979d45c8af70b443878adbb04bad439c9937a30bbecfc50b7005782bd01e3a87538220ca149286855129bd189f9bdb55ed1f7ab786f99c289032123c814e683db2f10970db79d2ef87f5a8a2cbbf7b9e2c447cb22d2a9d0f8c2b093a4d8aee57f0b05c2ac4f4ef780bad406b847d3c9d175f659105795236b072e96738043cbb8499292ad45acf7e576d8decdb635aeda6611da6c00a1badc11962dfa0643a83b865099de79416c86448280aad32f6797ef2fd879ba46abf36c9da45da4d0c936f6e25240cf30ffc79647720bf10ee18743f1ee3397dc0ed967445bb7b0df8eff0887d3f84abf20f0b2036837dd0308ed4a01f9d6447a9eccc9c471e75bd32f7d760216c326901ecd8590afcc2e697311e29f9d704dbeec409cc8c7fecc12fcf70cf9f718c12579fd17cef1e6bb44f89ad418005c2629a96275965f08c54a53e31cabcd4fb17021889bdcd4851ad33bb0d5438e55ba3b759dbf3c50fe20e6f3b8f1989f560818db1f2079b91b1e2d8bb22a7523c3137e9a30ab970f6019eca225e4b42bbe061f3b7b43":0
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 128 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"9200a0f688d86c0b6bfd9abeff66341684a373fe3f9a3057":"5c685c8596e374710fe327bafc45cd09190215fdcc03d010":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 256 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"95c9e644559919cace6f93f545dbfe48b130808ed66d0964":"7b8d1307e992221f6ffdcc7909d972d5f02e92187139cfd77f79345cb998bbdbabedb3ac00a6cdc4":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 192 count 7
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"ffdbcbd0abc94c7f15e5b6e8a7190f1ed4f01be11f4f7ccb":"e9ad95c8e9185a001509c50ae0098d45f7032575c7b8fd90a561716d2e5804fb":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 320 count 9
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"253a5cbe79a291c0af1a3d7460e7f284bd672cd026753fc4":"f71014ba711602df5cff2b93e86253775ea308bf83fde65fbc9a9a7852f87357330450072aaa3d6ef8dffbee20d2de7c":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-192 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"ff8666e4e538a6cf0a2a002b63716b06ec5f187785c2fc1b":"f5bfda19b535cf39e240d5b42db06f385fb002be273e46d9e5ceed6be4b5f636031bd0622ea0b3abd0087a7280844ce7260594201214e601ada0f686da6e9b45fedbe36c7d13db025746fa6bba2e540a417a29cdde32f9a7ff56325233bf60929bfd49f80e21acc23f3abf572d81e96b556f6f4f20a7e00c1cacd6fad07df30d40de593c99f73dbd61bf9d9d5269a56006ae85d588324f7e140d9775403af631e695f7856b1bcaa377aa7f4f12c68096a974ef703435102d7110f4eeaca787744c942be1186d132bff2b39f160157617bcead75ae59288880fc0e7db9877d854f553e90e1c917a99b8f357082c50bf3b71cd30d016f164ccb85bff50212bab13cca8dcfff0be984daead905ab13054eb12908a73f37ed42c5638a5a410ba182a2bee2caa84e76af2a715ddd24e837988ec475e506faa130f0241e08d92567a69c9645fc2be3945d65a77387cfa307562c9b6c7055f98956c547ccc109da9277292f47cf43e3cbc0d2e91c916e4fbd70df4a980e9430f5c1c8cfbd6c83f0f756c436bc07e86d5c75aec7e4c039349f71fbb959db709427a33869c523c3486be0095c1fd61ac912cafb9065b94916afd9166d73678ffbcc396a037ebe75e44cd824b2196903950b528f537c8baa70530251bfd8a6f37b202453993534c06aada0d1dbf760879d0898026997f1baf63e343e94ae076da7d41ea325dd23ff2a9cbee74baca05a538543d":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 128 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"e594f0067cedb74e883e7746d29ba725c884c25375323f367cf49d17ad0f567b":"3b51ae2b0e3ddeed94efd7bfdc22630187e1f7624d15ed78":"587e3f6c75644bb5c3db9c74714f5556":0
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 256 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"049c7bcba03e04395c2a22e6a9215cdae0f762b077b1244b443147f5695799fa":"776b1e91e935d1f80a537902186d6b00dfc6afc12000f1bde913df5d67407061db8227fcd08953d4":"e617831c7db8038fda4c59403775c3d435136a566f3509c273e1da1ef9f50aea":0
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 192 count 7
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"e86b9c1f74cc87ab8ca6a2fa1723fef173077e684345b90dacd3d485f587d320":"c97e8c25d498430300982cdcef592e34176e33e45cd59b19f7605f52e3c7b997":"261313cbea4b246e53affe1f84bd4c900c9b1d1842d79337":0
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 320 count 8
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"5b7f48b8ce77007481667e9900f3077a0c9407a70082b0de29bbfbd716a07149":"3ed16c7e4fed98d76092936e94fa5696c787ab63cb764e930fd37f917be4e7e60c90f327f0865d279e6c449b96301ed7":"4e0e6c45137efbf858ce896c815268a10d9869ef5668a90739b7eff99617691fe63b911afa53feca":0
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"9e92fc974e09541e6cdf1415575511436ac04a56db186bc0e60f0fac9bd58c6a":"201010a2a33fac1d20230bf5254204801de29e66cc44eb391b8e77284b3dbcfa3fabbdd4d9423d96af64ee0dde35786d79b7433021da27d6be753f91d2c1d63b40e9dc265b4a27cb2a61018a60ba5e29813c012b6acbf7d7d101ce227e45b5bc8a16c604c83a99ef35aaaa44fcd2033cddb6122db2dfb944d4b5c16dce911c5f4a1d8db46785534e7a090e31fd2192be64fe5b72efaa8b7965552bab4a20c8eac9a9e7b35e77df0277a90b0b1167e14a8be8d0bc37757354eff920ef93ad65c5a49b04bd553883efe9376811986002d4270d25c5749ee1454270a191084fdca53ae693f5a31b13929fbfd68b331a4fdd2259031f812ecf50d042a55fab302375057cb5b36735bcd2d75f745fd4a92580ecfd0fec44313ba9ca8cb1893f7a329638c17608c170de0ef68123c2233fea878fb1b49ec7478d9cf70591101bfd2d6b0328a27f7c497061b79289b6db4e46199c5db8121e9e1adcc8d64c85c27e329883775073d5f61b0bc470169ce8837b61fc23bbbe7e07d265b32cda5a94acea4bb2e52af17e13818a7ea424ca7fae7677caf405f04e37c2cad0c77eadfb4ead593f79ecbd8292e47b7838d775af9d9e252c6ceb147ccc2aadb01f8541871e5080109f9d94afc9103579bc9dbfcff8791d5eaa68521806590eeea74f411731b920a91c4f4542a60e6ffccb1285dd30e74292d5f37f33d4cb74742ac98c7a0475e069828dcd7d8301fc":"4b6f2257197b0692e6026d531bbe2f222a6764fe1cf277b0320a6bdf9efea0a3f304e94fd22372712f751aa377264b1600f3c1e7e0ada846082ab4885a5c9a51b1b25a593a269a7ca1b62a28f1a11b80fde57f0b9c0fc0e38e8edea8a294e18b4b1e0e24a5ae0e9d9fa0d8cf02378e592b322ff04c5a487332b5f58ad3fe9a0c20a205f6872c9e2d0c52c5b29c5c2f008444a3e8400b4822d39f646f9ed390c352615c4cca8cc0099ac1ec23ad7ef581ed33f9fd4a8a58eb240fc79bfc2df7c1606cc52fb97493fa59a0dc8dc01fdd9fc9fb51a2f1e9fd6a89cba67f001d105c456d99c3b1fd68dc9d01b1b8e0e4c2ed4eed63c0110ea6ee96b54eebcd56c5446dda210a9e143366014e72d5e4bf78bacc230641789ae7caa0e37682190d8007aad0a0983e7c970a6feb1112ee5920f628ba03493cc3b340aa9452e6698f818e6e409cd0a7f660094df05646ea0e6c6aa94e933f4fa4feae6207eb473f9d80e335d6020138f1fcd085a336bdea158823cd47079a89ac18bc8541918ccb6bbbe1aab5ba7d9c6b5fc9ba17cae707a556c2bf7d1f991f9a8ebe0f9aa6e395defecbb508cbbf68db8da443ce8fc40149c3c84314986615ca5685e5e2162ebc617929a7e402a6262a28e646d7f503253c30ff2e37ed6580676a9978aa2f5b4fe82e1c2fb83754fa855ee54a61e64a16b64a680732b14671ff55b3f2a6415233206188":0
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 128 count 4
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"08c936b25b567a0aa679c29f201bf8b190327df0c2563e39cee061f149f4d91b":"e227eb8ae9d239ccd8928adec39c28810ca9b3dc1f366444":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 256 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"605b22935f1eee56ba884bc7a869febc159ac306b66fb9767a7cc6ab7068dffa":"6607f5a64c8f9fd96dc6f9f735b06a193762cdbacfc367e410926c1bfe6dd715490adbad5b9697a6":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 192 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"81c93da5baa5157bf700fd38d7d67662670778b690cfbca9fe11e06268b35605":"875e1ca385586f83d1e23e44ca201006df04e1854e41b933fd607a7383ae1a39":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 320 count 4
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"c42c53da9bd5393e63818ecc1336ec6dfcf1d633e51ebb51c68fb0997c979e7a":"52f7b481f72bc2d41edade5388d38c2ff75765939576e49bab400040a14ff488848bef57d1502c06a3faad471f5c3178":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KW unwrap AES-256 CAVS 17.4 PLAINTEXT LENGTH = 4096 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"7b51259246dd7252f6a7215fb11fbeabfabafb0f8856afae525af8feb81d3490":"c625853da9fdb8665264c30539a258ba61da8bbd214f3f493e292f686dce73c003aea5c4070ea94b19e486019b18a2f3f1d836b85414bab14eb99baa283cafffabc8498cf1151489a6a6a0d01e7041633c94f9cc6cc3dfcd661c9c4a0bf77d9be168eec29cb0efef33c74d2dad18ae2ac2b5efb519f4c1f12eaa7a7d7959e7a6dec681e4d1878b20054b7925d2da0b2f8730604445ff3fca3a06285a4a2d86648f10a2bc3cd422646f70224ec9025e7ce701c8b521c0392fd7d2ac883f2a37bb7e4d53a92a620e65e090b91dbcdd616a13b3948eb1b5a6b1bde80f03dad61aba3223fd91ca3df68b0749fd049813a7ab0268445793b16677bc1af00f877097cb14798777ac817d0df82507aec246f755ddf95b19bb56ef9f2e730bcf2863648d8b164656df37977d54eaf05063b0ee8ba61c2a2ba7dda8fae337d5f6ba965d9e643b4534ed9f4eea7b2b26680fff50260e245fa0d63139b40e2f152da3a976589e957be22cb0885cd582aa9468b08f08a22b486767a6b99c1778ecbd763ebfe2bd83c6191f4e8a84972e4920452b2b2dd28be5d7bda05dc3422419793ca8c26defd3b42b2cc99bbad98e7461f034abf137d7b3166c94e20bdba091653c6a17ccc4faf86a7ba6d2abc0ecada9103e73d9ee4659b6e991a1a209d2ebd96c24759c69ad13a03431ddc05abc20dc8581b1e526f4d98f6352ca4c77f5479db234125fa585ba275fbcbdbf":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 8 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"20501013aa1578ab32704a4287029098":"382179a39d75756f57763486d038b50f":"14":0
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 64 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"a099fff482dbaeb53aad84f81b916da0":"b831c7137facaed059cbf268767e230f":"0d24299443bcc444":0
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 72 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"4d49e260348172c38a79eb925b189b12":"54755a93ff5173aec60d1eaa8fd7d4090f00f638c2831aa9":"2bbe64479da7c45976":0
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 248 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"6a5a5ac4ccedf055d7562ac58ee7819c":"46904a5583e8a22f4b2f5aa8d071f5cbfc938130f1b33f2e6401aee7cccdef2159a89c9b682cfaf4":"33ac6837955300e569b29958985cdbd434c18208779a949d20b110b0b719e1":0
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"1dd51f0d3a0a784174ba81b2c9f89005":"e1bde6d2df3b8e48ca127f97b56b5dc2672b3736cc3157c7b80a0316ef1efbdbbce19fea23da831836ccd2e002b2c1dfad206b5cec358446b8434d7f4c39e65b0e0b50897642ffc34bfb3cb3e233aa9c1058ff0d4fd48e98bc8cc3d214c06d514dd97db2278093a308f91f4ae92626d85771fb1447b36a3467fff02ac7e81ddbd0fdbcd02d1acd4f053c989ef3dcc2c01e23bc2f6090f3e8c0ba5f0082341200b1c37b99daa9cb6fec78bce3429aec5badb9fd28fdbdbdc5d53570675a9e39535b4594095658ef950ecd79a162223b60d2eb91765e022dc6e1bbdd86f1bcc280ed9df350da08a801fa16a1bf2701947acfb08f19fdfcaa1d76f466a5de2458a78fb82f6af3e1be68f405a4289f25896f4c9830005c9e895c86e67eceab0ad544856071b8d9585835b5e85a07ab01515f7ab54f98dffb4ca49a15068eefc6a01f7f52fd1adbe3631c59f6f43f79d2b4f2a691e2b30bb1d43a848dc3ee39c7f2e50f0c9deb7ab51e33bf40903ac255bb1510fd61676a6c13c3c776b8aacc6cefb95e24973ebb11192e2692dd0c6a085b58f86e11cc28ee2194988c123e3666da7339c0a4ac6afbacc83f1f100fbb39efff7cc605c9213828224a17c476395aeb9bb0a3150fb8889a8c2a494c8c526203f261642bfa69a94b86de9e6d3d932fe20fffe4bd76d502c0d437a3e1d0d8727b7a8dc0e361967109e93566326b6c517663731c4c9bdd0295d8":"1a4eed4bf5b8d2e2a58f1f1277f164cc32cdadaed848f76fe634034082ff9aa1711870bf3936d01a2aa48de30de5143b9148cf56f4490f9d480dda0b672e8e17a012cd26cec3c68837bd5b2f9beb13e0110f21c6c36343e09e027f39557d1596d4ca406e3e7aa113e9bb8623106bae25f0ea23d46bc29970ba2596f83fe4f73a6f978a4d949fa7c271570a2ae5d2b50792d5ab5c43d455f359fb83c35ca3da37cd73cd66b6adce94d78ecdeabf667daa47ea70799af299e1d898ccf3fca6c42c6fff8cf2ec992f596fed4a0cdb502a00f9b5689302931d15cba691e2f8079a0411332438b714ace5234b91e4aebee8f8dda0e1968c2016fed350430a65d8d206c9436f40b79ce03083b8dc207d6960be1ce97007ed22a388ebb7b3d8f7d2b7d9f8f49731fbcb21e21db0cdd15674c795d5af2b2cd727f83e634e8c47157ed0c6873a5c9419e683f16f4a7827b444967812f9d1adb9201b89a0e66bbcf0591465f5d7036a21cdda0e10099feb819dfc37fdd3105120044dab716882d3971f312e3f4459006fd5a1eab08ff63edf6718f47ddaa37f7f40c9c372995f3aec97bc45e287b64fc8cf5559ab04a4d4d3ed482f5d61d3abd99cc87ee406da3ab9c9cd22ba3b8d191b26754aa94a2412f39e332d77fe72210adb0cbb5c96adebdbde036f1f1aaafad74a7ac2594f81efa734054e2e16dc931d49b970b81756862705fcd4":0
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 8 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"30be7ff51227f0eef786cb7be2482510":"7f61a0a8b2fe7803f2947d233ec3a255":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 64 count 7
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"9ad15907cd05d77b844816b1dd806c92":"7aa0e5d322363afbdd71b531e50d4935":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 72 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"2005cbe9cc66a35cafdff1af119ae6ce":"60f9c736ec3619efdcc7cccc6b90ae5cdb8bb9eceea5dd96":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 248 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"2c3b49efbf60ed01a3ef27ee24ac90b0":"5fa5a87bec09a3e05864656f8966cd38e1c4af48a06b1dab4ec9cca35dd0f92b54015fe5332bdef9":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-128 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"4b4c43c9de4fb4a2a7a7adafeabe2dbd":"6e4d08b8124f7d3e23303fac1a842014f95e3d71c438f8f1990307842796dc5e404ad81802e35c183fe000390a12c81ee684c5cf26c1d90e414cfffe6931b0f352936fcf0b31429eb5c7612cc359a15371390e518cf5c6a6bff1bb0348d14e2c39b98c9f30672ed2af1d96296df8b5567db25b9510a2083461810e119735490058ed1b46b7fdfa885041d8749f90a072b43ba49f2f51fbcda0dbf3cf99fca1d8f46330e5f6fe079d6679cfa26214c8831b782aaa023a2e0ea91050d277dab876aa6865f2bb3fc1a4a77db52f6179d5e5325993280948b6b7002b572829641d35ed3d735d8423e5b24673c4570ca25064fc2c2ad4840632536bcfaf2a7a814f3eaed92b4d501bc51c1719a0d8d8f420b66db845682bb41c88038cfedf13417143a3a701b521a9bf0bb639875a728c3b5ce6ca7e7a45bc75285c193902e6b5e7a4c6e720493d3937bf485e587bff894f70fd6165a1d0129cc673a992e0a4f5489d228a066b1df60002ec0521924f8d672cd1452fec927e58e75807b2a390256f920743fa4d0fc8f59f2469a595ef65095ca0c80adfc843e9e69b6d4a3f824af47b2bfbf2a7a6c1b650378f096f6f0bfabc752c8f279d4f45d56d09dce97962c119de3a64d83b93ea55066f24d4238a229ae86e6a7857af1d8aba823370a72fe358046049a84a70213ef31d9e77a722def8e21480e79b71299438070946bd459a7251707446c911e381":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 8 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"716da5cce5877d8f305b5478d671f6c73eb1bff4de15df07":"dbd5247ad2445575cafb00ee7707c218":"bf":0
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 64 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"b94bc10b85a8c2f74a66fa723a25ea1b398a4f627efe1ce0":"18eef64a022b2c7db27648cbb5f1d5e6":"19c0f2f78606fae7":0
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 72 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"f61cde8e515d59a8ca95efb1a98ed4216c4a9649151babf2":"83fce85e9bfc6ed784b052472e5780fee662f17a91faf1a9":"1c6883862ede37b31b":0
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 248 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"1c883af75147bae6f34205cd656ad30ec97e617456591ce6":"f24f6747711cf72fab0422026c6d548ccdba786d77ab900ac3fb8f39f116d38e92c82d5fd9a045dd":"bdd793f086d8733f69055bd79bbc448be857286e918fd4c54be4acf4eca5e4":0
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"1b38d4b366f844e71a8db6be2b77a05a9e81720d2d3f31ee":"62ddc158ecb048250bde439dc7aad34dbe7667d330a349026266c24cee9742953b623d1e247e501641b45b60cfbab665e68040ce06ebce478d9d77f5f344943a1edb14f0d9f165ecfe407031707961fedcd016559228bff5761cd6542944a5d86f9acf4e0a4114682c2312b8d4e8285d3efe1a7c1526642c73c332a9e484377a1c86714e3cb687781928c8a5fe28b4aa74e79f53ecd00793e00041b39b172e5fedef3d4164dcc6b2d2e47994e73f2ab048a4adb8cd94fcd7767314ae40f8cdbef2b26d25f74277a2f88f1de56342a0ec97fde4df2d052e6ebc62622f65725d845f670a647808666c7325725a3428e26fefe725c2badb8a8b8f04e30456bd1fd39fd0f7c782b7a2bc9d8c53922a54c5f103551271af6d7243133b96cd1c108811e4beb9a56472c1f9823a1e88832c5505e07cb93b9041f4b8d69cd27403680a18bb3848c269babbc52aaf568ee8245f4f72e177257103dd4bdffeee9b48e0660d6c2f4dfdce52462d0ed5cc5114dc0aa5a35601c9a644a1fdd3c57c3153e65a108eb94eea3bc9979a67a2f569eb7398a4bd24547c15faa361bb2950a379a1cad1737f56e7c210652aaea7581f39f07ee09a101fde8c34c3cfc404f2b8f682735fc4c721eceb4bd2295d8a74ee3cb858329509eba9049e7e791e04d8452b50c6e6225b94a8cc10ec1d262588fd2f05eee08113414e770c83caa84d310559286c393799117c177089a2":"b1c88d3e5648218ee085abcfcaf7f362f33e4d6de363cb84182af9f18a31475f0e14ae8eff76ca67455726392a110ca262b90d040abf49beb036db096be053d493787a67e983b63945277044acf648172c75b38d7f81dcd58e3bbcecb963dc95863877784ac04eba83481152c30b1ca9e9b78fe537deee6c95933e1b5fb414cfaf7ca1dbbae8b114f0538f4cbf433ef214b776faec9ce1d29f680f4c88ff7b9ba0e964898dd253f5f82ec9f25663ece9dbff5e284f63b0e0fd07fb13b41aa8359f1ba1666bcb26e65d28b1f899952beb28b8f902f048e31efb6ab4817cafc6d84c7f4676b50936715667a67df7ca965b3ab2a5fc472375b1446c810242eb1cb78b9ac496ed4715e0f89a4e1ae0e2724edd59c954f54196ab55ac1947528fa14e716b7707aeb023bd0a2242da7ac97f3feb7795d9be05cd5b1cc33095599ab4c4d8d583c9e2a4d4ed12b836722370569737fae2d6fa60c8a5b8a80fd71129fe29395746eb746528a8845c5a9d50e7bc4372e7f3f9c6333feec791529a6ae1bc0f620feb604f56969e4ea3445810c72dd0772856feb58f09796f461f7ab1b454c303c810eec7526aeb397520b6114f57a4d906e974e8d4a910afafbb0f030b18887b951052d18578022cb7e33408578cdca34f32012f62d3dd35cb74e9d0fecac52231c5cf5a34d470d3b5413644c4e2af1f1613093a3b0550f8df26d033a35b9b":0
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 8 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"df8f5124b1e03228f2b96f0df31924bac1d3b5d094da22e6":"230bb26c1ea9d5c8fcf7c122ea994f41":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 64 count 7
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"94c8dae772a43b5e00468e0947699b239dfe30ab5f90e2f6":"239c6bceee3583fe7825011e02f01cc0":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 72 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"d81b7162dc6e9e18bea6e258bddb53a1c9f22a4a7177d9dd":"4f3a2b7b229a665776f9cfa42e0c2a615a81f69cc0f0f465":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 248 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"688833d56cf1a0f492bf1f7e35c2fa6299a2b1b5ca2a2823":"4b7c17d7a7189e7955c03abb0ca95fc0c780953787972097ae596d46fe2a8cd75995e6309780ae5f":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-192 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"4b0faa630930b0ff8e624aeb4ddfa018a858cfa653132675":"1640db081e87ef7797a9f17509f5bc67d40beaef096131748f413cac3d2500462b61140b31bc3965958af51351903549e4a71db589a6bc67d72ec33b8605a25a539a2043704389e3e0781152dffa9b64d6ec186ed144847434345e6dccefbe26626eebc4c22e3957b2145c46fa11d7819d4195cb43a9db8d2de507c023607548b56a07628ce4c706939fde1bdef8364b2b8fb7db30fc5c8e99f29876130d9f71a8486d99f2c7fc09f646918d4c60e53c7b9f9a8a1e9a023d70448f6b79c3f35cc6b9ace0535147f7f27be66d918895b9106cc83eda1aacdc2bfb7daa75b2867ae63109ecbf9423526511c64c4261e395d9b5a68dd2503ada57cf1b8a18336b8d63d248ec4dedb6e30662336546c86ef83b53504bc3bedd85a027b6b9f0323bd9380d9ba696b77072d98f96b77f9b3ad9e219715122b2dd033529eaf7ecced8be6d1e6467b8e4a61105be9b7a7ce208b6dd6bd34481f80b3bf534fb87904d45986931a088480a8040047c681dc4e8ec1c625a5449d9ab28709d04989c4b1a4ef0f1e379d37fe6f0641b9e705207e9a0652463cd5da71cd50321116d4ff1cbae08063df336482eadc0d117bf119e01f2577afe182e7fa477ec53b754e347a2c742960b9bd355f969e6ae1df2210e75bb44c598b683dd4c8692f4cd1b92125ac9ed10ec4cef6289d3f815cb894e74dff0bb72d51c43cb420d74a31c681c10ad7f9258d77f1f186c926a":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 8 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"da862b25a629d328cf9fac7be0d6ead1cb2404e9bab87a2381a46eb1a81187c5":"5e01a2b9b8413f303a3578d2cc255fda":"d4":0
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 64 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"362586d516d38e4d58b50a441443e75064cf6d6cdb6420862932ba7b0480b0fd":"ea7ee0f5af3a271a9777838ed13c61af":"f1b92d0db744bfee":0
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 72 count 1
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"0e6d542f960c7e61ca190d7fd719fda157030a0a013164613a8c522b52ae685d":"b5cae8a82095abb3478ab167dbc0201d2f4dfc5f81bbe44e":"a957eb4ea02e68ba8b":0
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 248 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"0445b86d13b7b76c0089a63dec70c32fded9607af63714b7c3cc724f49c1c6e2":"7f63167976e71e43b7b135c8cd12148f826f56e73f6fb6e7f6cefa23c34302ff374d44dd66b6bb01":"7af8c3b32e61f8b5c027383a273927b8fd09b75692bd0b713ec8ecec0bdd2c":0
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"08f5c088acec18e6cf1f03a8f85d772e327e7fb07f8c2939eb554e84c42ab93d":"dff30fd43647d4be54cf2dfd6187e2ddffb55267313f980fb09c833a9c2bfa558a95861711f0acb2a5c7e731ba22f24a9c4dfdd9e9b0216e9088f817a175b9835b0e17615687a20f68c067205626494cd04fbabc0b3eea7c0a4cd6236bc8b3e52e721dfc357fb8a3722bfcc4c690d8f63dbb864bb6e3a15805aea7270f8eb748deebaa2d066fcda11c2e67221f9a91d2c29a6c79ffae76aa80a2590b4f9e35f623fbf2f8ceb2a205493077556a186e25e5bd52dcff7bcc6909b37a66c1d1431be1b363bb40da25386eaaf5fcabc7be6422a04434a21d1d3105328e7c56770b9f59b03395e4138f5f06fc7e6b80dab87b08caa7bfffc45a095c15263efd3f06c651ded6f58074efc20620d704997fc84721a0a8e9e5b9f5cd330bbb156b31d9d1b1c260e4a24535f30404dc5b2dd6b35d916a1391b25a7d8790be09d85483ed1522074a2785812005bda10dd55acb245b3bd3d9bb777dd23f9b02538ba1a114ba53386d7ca4d9524b2f8a18e0ffb21580b560540bb2146f08f04974b90eb324547d56222df95f44bc6e5f183bef283e4816fb1b2933f9c7c6726a245a495e304d8318d0008c51b0be8090f8f668fbc3f31e073be4b9e97468f4dd8c798e9d682868df493db8a85738b58cfd005190f365849072577772672c6f82555c65046eb34e86fe61103327a063bacbbe33cea7eaa3d1de45471b7269e1b6b38608626e323447a3d5fe0599a6":"8b68f66a3d2f59d419851b94d9a6f2f0e667f8125e11d463a6bc2cea46b12dcc40ce8018b204972c735fdd6d2d05b628f4905c6690f5ac5b1b51e12f3af2dc3ae9b9dab616f0a2a66a1ac197592fd5b15900547f32f54110b58d51a0340aa80e9eeb7b2e0eb97e80aa22ba918f2fe1c678c730ed5c3d8d24774f17d8ab6e01a06243d36e764df1dbb8af1faadbc55281f0242abd7a162c984fd0b05ab8b0bcaedffb2962024f009a8d7c9e71281c09f52ec0707ee3bbeb1ecb918be6ae3e9c1fabbcd3512af928db3ba6c109ff9e9839a616b2a53f092160a48222b84d53cd52490515ef93e1ebb33897263492ab8ec6fad2e633276ae367f76d7f926309478c0205d4f22506a451795dc98f5410d8f5d3e049cbedf381620861e7b4ae08f2d8a71abc1f230248cb636a2d7b4e7717ab2b7b5f2dc6e5b5a18e8043254208b50fd6f8929eaf974c48551233661ad67321b64d69245d536d9a8ca2a6a10966dddb9d2ce36641c9281c460ae524b077867258f638e6ac872cb5f5c6fb216b1ae60a9d0c5ea0dbcd060f255da26111175af4e9935df59ddade6a2a70cddff8cae6a98e4f3843c2dd59d09053b07b648a46f5de0eb21ebb192828279a386ea3eedf2cdc355d73d51111e8c1d522e059752bc56226a4225bcab713bfaaaec78167d7cfd33e913b26fda93ca7524aa8a8b17977c88ff9bc23ea810b4de59eac18d1523b":0
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 8 count 5
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"5fc3ef43eef256993fb00e6ccc90f60319f10a3bc9fe5ca4ec876c165e2a7720":"f3d922a948969acca293bc3daa027e48":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 64 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"398444df32841be9e699c64faa92630c834564b8384876dceb471c4056fc8299":"30032c9a3ed00d29512d8c725fa86a4b":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 72 count 0
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"64b69233fe392c0bcda28a931cc3527b1a8f29235c1adf6256556c685cb89b9f":"6b5fd75ad16eda04a8b29f1bc0411ae28befbad9e474f2d8":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 248 count 2
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"8c35fb77766d04f48d5b52275c5c5f31f568078419e5c2335918965fbe53cedd":"bacccb1714dbaa4908c2654aa8dbb1ddbddd8ab819429b026619fb1c0fa75a8247372b2feeab1e1d":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+NIST KWP unwrap AES-256 CAVS 21.4 PLAINTEXT LENGTH = 4096 count 3
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"1726706350c11e6883955f24ea11ab247ce3b2ab54d05e67ad9770b5564483dd":"b006f26a67d0e1e2cbeb5c23b6b300adc1526d1f17bbe964fe8237ae244878158e6b04cb488786b5258ac973c3a2eafd7fcf3a7ca6c825155659fbc53d112bc78b3a770cf059fdd5e68f2b4bfa36de3721231102e5041c947fba3d906bff39592ec3901a398da23035f1190e99b58659330cc2e856ee87ad4197dcc7d16e1f062275bced1ed5cd82163ae3e58da7368dc2aadac855385bd4fa0b8baadef608d0a5c27172d12b88c70b136eeccf37f36364361a990dc50815743cab1636e661bff04ca8345520c30b935a060b450526b1d6ac09170e5b0a327b88f42327b85c9a621d2ca745963c2815a2bfcf509d50b6058ed6e67f369b5608d2aa885238b67d1b8e0d83f9464aa473bf109350fcc02e360c2619236cbfbf895b607895530d8d3d2e41450750dad05b1c37ef15db7fb4707597ac252e8e58d4c1ab2713b427643d198164c908b5d8ff36e9700157284009c7b283633d8b27b378bb65eff8aa59b5fe5e6437a1d53a99c106c2c4d033d3d23950e313a10eb31d68524ae9f8e4f56437acf66db3e8f77407a15bbff4b393e5559908993146d93c673d2aeb7d4cb8fc8d0169de7ed6e2bbe6ce9958a0f5d201419e7acb17e47da827ba380d6b3ad3b5a8c2101c5fb501110c727169065f23297947f538ab3ec165d61edc1f6a9e1735e9b7fc06d4d3406cf8f9c6a68b196cf262324a986705fbc802cdd2e6b4ebcf68e6bb9e793ae644":"":MBEDTLS_ERR_CIPHER_AUTH_FAILED
+
+KW AES-128 wrap rfc 3394
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"000102030405060708090A0B0C0D0E0F":"00112233445566778899AABBCCDDEEFF":"1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5"
+
+KW AES-192 wrap rfc 3394
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"000102030405060708090A0B0C0D0E0F1011121314151617":"00112233445566778899AABBCCDDEEFF":"96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D"
+
+KW AES-256 wrap rfc 3394
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F":"00112233445566778899AABBCCDDEEFF":"64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7"
+
+KW AES-128 unwrap rfc 3394
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"000102030405060708090A0B0C0D0E0F":"1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5":"00112233445566778899AABBCCDDEEFF":0
+
+KW AES-192 unwrap rfc 3394
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"000102030405060708090A0B0C0D0E0F1011121314151617":"031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2":"00112233445566778899AABBCCDDEEFF0001020304050607":0
+
+KW AES-256 unwrap rfc 3394
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_unwrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KW:"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F":"A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1":"00112233445566778899AABBCCDDEEFF0001020304050607":0
+
+KWP AES-192 wrap rfc 5649
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8":"c37b7e6492584340bed12207808941155068f738":"138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a"
+
+KWP AES-192 wrap rfc 5649
+depends_on:MBEDTLS_AES_C
+mbedtls_nist_kw_wrap:MBEDTLS_CIPHER_ID_AES:MBEDTLS_KW_MODE_KWP:"5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8":"466f7250617369":"afbeb0f07dfbf5419200f2ccb50bb24f"
diff --git a/tests/suites/test_suite_nist_kw.function b/tests/suites/test_suite_nist_kw.function
new file mode 100644
index 0000000..eb67c03
--- /dev/null
+++ b/tests/suites/test_suite_nist_kw.function
@@ -0,0 +1,343 @@
+/* BEGIN_HEADER */
+#include "mbedtls/nist_kw.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_NIST_KW_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST:MBEDTLS_AES_C */
+void mbedtls_nist_kw_self_test( )
+{
+    TEST_ASSERT( mbedtls_nist_kw_self_test( 1 ) == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_AES_C */
+void mbedtls_nist_kw_mix_contexts( )
+{
+    mbedtls_nist_kw_context ctx1, ctx2;
+    unsigned char key[16];
+    unsigned char plaintext[32];
+    unsigned char ciphertext1[40];
+    unsigned char ciphertext2[40];
+    size_t output_len, i;
+
+    memset( plaintext, 0, sizeof( plaintext ) );
+    memset( ciphertext1, 0, sizeof( ciphertext1 ) );
+    memset( ciphertext2, 0, sizeof( ciphertext2 ) );
+    memset( key, 0, sizeof( key ) );
+
+    /*
+     * 1. Check wrap and unwrap with two seperate contexts
+     */
+    mbedtls_nist_kw_init( &ctx1 );
+    mbedtls_nist_kw_init( &ctx2 );
+
+    TEST_ASSERT( mbedtls_nist_kw_setkey( &ctx1,
+                                         MBEDTLS_CIPHER_ID_AES,
+                                         key, sizeof( key ) * 8,
+                                         1 ) == 0 );
+
+    TEST_ASSERT( mbedtls_nist_kw_wrap( &ctx1, MBEDTLS_KW_MODE_KW,
+                                       plaintext, sizeof( plaintext ),
+                                       ciphertext1, &output_len,
+                                       sizeof( ciphertext1 ) ) == 0 );
+    TEST_ASSERT( output_len == sizeof( ciphertext1 ) );
+
+    TEST_ASSERT( mbedtls_nist_kw_setkey( &ctx2,
+                                         MBEDTLS_CIPHER_ID_AES,
+                                         key, sizeof( key ) * 8,
+                                         0 ) == 0 );
+
+    TEST_ASSERT( mbedtls_nist_kw_unwrap( &ctx2, MBEDTLS_KW_MODE_KW,
+                                         ciphertext1, output_len,
+                                         plaintext, &output_len,
+                                         sizeof( plaintext ) ) == 0 );
+
+    TEST_ASSERT( output_len == sizeof( plaintext ) );
+    for( i = 0; i < sizeof( plaintext ); i++ )
+    {
+        TEST_ASSERT( plaintext[i] == 0 );
+    }
+    mbedtls_nist_kw_free( &ctx1 );
+    mbedtls_nist_kw_free( &ctx2 );
+
+    /*
+     * 2. Check wrapping with two modes, on same context
+     */
+    mbedtls_nist_kw_init( &ctx1 );
+    mbedtls_nist_kw_init( &ctx2 );
+    output_len = sizeof( ciphertext1 );
+
+    TEST_ASSERT( mbedtls_nist_kw_setkey( &ctx1,
+                                         MBEDTLS_CIPHER_ID_AES,
+                                         key, sizeof( key ) * 8,
+                                         1 ) == 0 );
+
+    TEST_ASSERT( mbedtls_nist_kw_wrap( &ctx1, MBEDTLS_KW_MODE_KW,
+                                       plaintext, sizeof( plaintext ),
+                                       ciphertext1, &output_len,
+                                       sizeof( ciphertext1 ) ) == 0 );
+    TEST_ASSERT( output_len == sizeof( ciphertext1 ) );
+
+    TEST_ASSERT( mbedtls_nist_kw_wrap( &ctx1, MBEDTLS_KW_MODE_KWP,
+                                       plaintext, sizeof( plaintext ),
+                                       ciphertext2, &output_len,
+                                       sizeof( ciphertext2 ) ) == 0 );
+
+    TEST_ASSERT( output_len == sizeof( ciphertext2 ) );
+
+    TEST_ASSERT( mbedtls_nist_kw_setkey( &ctx2,
+                                         MBEDTLS_CIPHER_ID_AES,
+                                         key, sizeof( key ) * 8,
+                                         0 ) == 0 );
+
+    TEST_ASSERT( mbedtls_nist_kw_unwrap( &ctx2, MBEDTLS_KW_MODE_KW,
+                                         ciphertext1, sizeof( ciphertext1 ),
+                                         plaintext, &output_len,
+                                         sizeof( plaintext ) ) == 0 );
+
+    TEST_ASSERT( output_len == sizeof( plaintext ) );
+
+    for( i = 0; i < sizeof( plaintext ); i++ )
+    {
+        TEST_ASSERT( plaintext[i] == 0 );
+    }
+
+    TEST_ASSERT( mbedtls_nist_kw_unwrap( &ctx2, MBEDTLS_KW_MODE_KWP,
+                                         ciphertext2, sizeof( ciphertext2 ),
+                                         plaintext, &output_len,
+                                         sizeof( plaintext ) ) == 0 );
+
+    TEST_ASSERT( output_len == sizeof( plaintext ) );
+
+    for( i = 0; i < sizeof( plaintext ); i++ )
+    {
+        TEST_ASSERT( plaintext[i] == 0 );
+    }
+
+exit:
+    mbedtls_nist_kw_free( &ctx1 );
+    mbedtls_nist_kw_free( &ctx2 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_nist_kw_setkey( int cipher_id, int key_size,
+                             int is_wrap, int result )
+{
+    mbedtls_nist_kw_context ctx;
+    unsigned char key[32];
+    int ret;
+
+    mbedtls_nist_kw_init( &ctx );
+
+    memset( key, 0x2A, sizeof( key ) );
+    TEST_ASSERT( (unsigned) key_size <= 8 * sizeof( key ) );
+
+    ret = mbedtls_nist_kw_setkey( &ctx, cipher_id, key, key_size, is_wrap );
+    TEST_ASSERT( ret == result );
+
+exit:
+    mbedtls_nist_kw_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_AES_C */
+void nist_kw_plaintext_lengths( int in_len, int out_len, int mode, int res )
+{
+    mbedtls_nist_kw_context ctx;
+    unsigned char key[16];
+    unsigned char *plaintext = NULL;
+    unsigned char *ciphertext = NULL;
+    size_t output_len = out_len;
+
+    mbedtls_nist_kw_init( &ctx );
+
+    memset( key, 0, sizeof( key ) );
+
+    if (in_len == 0)
+    {
+        /* mbedtls_calloc can return NULL for zero-length buffers. Make sure we
+         * always have a plaintext buffer, even if the length is 0. */
+        plaintext = mbedtls_calloc( 1, 1 );
+    }
+    else
+    {
+        plaintext = mbedtls_calloc( 1, in_len );
+    }
+    TEST_ASSERT( plaintext != NULL );
+    ciphertext = mbedtls_calloc( 1, output_len );
+    TEST_ASSERT( ciphertext != NULL );
+
+    memset( plaintext, 0, in_len );
+    memset( ciphertext, 0, output_len );
+
+
+    TEST_ASSERT( mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+                                         key, 8 * sizeof( key ), 1 ) == 0 );
+
+    TEST_ASSERT( mbedtls_nist_kw_wrap( &ctx, mode, plaintext, in_len,
+                                      ciphertext, &output_len,
+                                      output_len ) == res );
+    if( res == 0 )
+    {
+        if( mode == MBEDTLS_KW_MODE_KWP )
+            TEST_ASSERT( output_len == (size_t) in_len + 8 -
+                         ( in_len % 8 ) + 8 );
+        else
+            TEST_ASSERT( output_len == (size_t) in_len + 8 );
+    }
+    else
+    {
+        TEST_ASSERT( output_len == 0 );
+    }
+
+exit:
+    mbedtls_free( ciphertext );
+    mbedtls_free( plaintext );
+    mbedtls_nist_kw_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_AES_C */
+void nist_kw_ciphertext_lengths( int in_len, int out_len, int mode, int res )
+{
+    mbedtls_nist_kw_context ctx;
+    unsigned char key[16];
+    unsigned char *plaintext = NULL;
+    unsigned char *ciphertext = NULL;
+    int unwrap_ret;
+    size_t output_len = out_len;
+
+    mbedtls_nist_kw_init( &ctx );
+
+    memset( key, 0, sizeof( key ) );
+
+    plaintext = mbedtls_calloc( 1, output_len );
+    TEST_ASSERT( plaintext != NULL );
+    ciphertext = mbedtls_calloc( 1, in_len );
+    TEST_ASSERT( ciphertext != NULL );
+
+    memset( plaintext, 0, output_len );
+    memset( ciphertext, 0, in_len );
+
+
+    TEST_ASSERT( mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+                                         key, 8 * sizeof( key ), 0 ) == 0 );
+    unwrap_ret = mbedtls_nist_kw_unwrap( &ctx, mode, ciphertext, in_len,
+                                         plaintext, &output_len,
+                                         output_len );
+
+    if( res == 0 )
+        TEST_ASSERT( unwrap_ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED );
+    else
+        TEST_ASSERT( unwrap_ret == res );
+
+    TEST_ASSERT( output_len == 0 );
+
+exit:
+    mbedtls_free( ciphertext );
+    mbedtls_free( plaintext );
+    mbedtls_nist_kw_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_nist_kw_wrap( int cipher_id, int mode,
+                           char *key_hex, char *msg_hex,
+                           char *result_hex )
+{
+    unsigned char key[32];
+    unsigned char msg[512];
+    unsigned char result[528];
+    unsigned char expected_result[528];
+    mbedtls_nist_kw_context ctx;
+    size_t key_len, msg_len, output_len, result_len, i, padlen;
+
+    mbedtls_nist_kw_init( &ctx );
+
+    memset( key, 0x00, sizeof( key ) );
+    memset( msg, 0x00, sizeof( msg ) );
+    memset( result, '+', sizeof( result ) );
+
+    key_len = unhexify( key, key_hex );
+    msg_len = unhexify( msg, msg_hex );
+    result_len = unhexify( expected_result, result_hex );
+    output_len = sizeof( result );
+
+    TEST_ASSERT( mbedtls_nist_kw_setkey( &ctx, cipher_id, key, key_len * 8, 1 )
+                 == 0 );
+
+    /* Test with input == output */
+    TEST_ASSERT( mbedtls_nist_kw_wrap( &ctx, mode, msg, msg_len,
+                 result, &output_len, sizeof( result ) ) == 0 );
+
+    TEST_ASSERT( output_len == result_len );
+
+    TEST_ASSERT( memcmp( expected_result, result, result_len ) == 0 );
+
+    padlen = ( msg_len % 8 != 0 ) ? 8 - (msg_len % 8 ) : 0;
+    /* Check that the function didn't write beyond the end of the buffer. */
+    for( i = msg_len + 8 + padlen; i < sizeof( result ); i++ )
+    {
+        TEST_ASSERT( result[i] == '+' );
+    }
+
+exit:
+    mbedtls_nist_kw_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_nist_kw_unwrap( int cipher_id, int mode,
+                             char *key_hex, char *msg_hex,
+                             char *result_hex, int expected_ret )
+{
+    unsigned char key[32];
+    unsigned char msg[528];
+    unsigned char result[528];
+    unsigned char expected_result[528];
+    mbedtls_nist_kw_context ctx;
+    size_t key_len, msg_len, output_len, result_len, i;
+
+    mbedtls_nist_kw_init( &ctx );
+
+    memset( key, 0x00, sizeof( key ) );
+    memset( msg, 0x00, sizeof( msg ) );
+    memset( result, '+', sizeof( result ) );
+    memset( expected_result, 0x00, sizeof( expected_result ) );
+
+    key_len = unhexify( key, key_hex );
+    msg_len = unhexify( msg, msg_hex );
+    result_len = unhexify( expected_result, result_hex );
+    output_len = sizeof( result );
+
+    TEST_ASSERT( mbedtls_nist_kw_setkey( &ctx, cipher_id, key, key_len * 8, 0 )
+                 == 0 );
+
+    /* Test with input == output */
+    TEST_ASSERT( mbedtls_nist_kw_unwrap( &ctx, mode, msg, msg_len,
+                 result, &output_len, sizeof( result ) ) == expected_ret );
+    if( expected_ret == 0 )
+    {
+        TEST_ASSERT( output_len == result_len );
+        TEST_ASSERT( memcmp( expected_result, result, result_len ) == 0 );
+    }
+    else
+    {
+        TEST_ASSERT( output_len == 0 );
+    }
+
+    /* Check that the function didn't write beyond the end of the buffer. */
+    for( i = msg_len - 8; i < sizeof( result ); i++ )
+    {
+        TEST_ASSERT( result[i] == '+' );
+    }
+
+exit:
+    mbedtls_nist_kw_free( &ctx );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data
index cbbbd5b7..4add252 100644
--- a/tests/suites/test_suite_pkparse.data
+++ b/tests/suites/test_suite_pkparse.data
@@ -207,15 +207,15 @@
 pk_parse_keyfile_rsa:"data_files/rsa_pkcs8_pbe_sha1_4096_rc4_128.pem":"":MBEDTLS_ERR_PK_PASSWORD_REQUIRED
 
 Parse RSA Key #35 (PKCS#8 encrypted SHA1-RC4-128 DER)
-depends_on:MBEDTLS_DES_C:MBEDTLS_SHA1_C:MBEDTLS_PKCS12_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA1_C:MBEDTLS_PKCS12_C:MBEDTLS_CIPHER_MODE_CBC
 pk_parse_keyfile_rsa:"data_files/rsa_pkcs8_pbe_sha1_1024_rc4_128.der":"PolarSSLTest":0
 
 Parse RSA Key #36 (PKCS#8 encrypted SHA1-RC4-128 DER, 2048-bit)
-depends_on:MBEDTLS_DES_C:MBEDTLS_SHA1_C:MBEDTLS_PKCS12_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA1_C:MBEDTLS_PKCS12_C:MBEDTLS_CIPHER_MODE_CBC
 pk_parse_keyfile_rsa:"data_files/rsa_pkcs8_pbe_sha1_2048_rc4_128.der":"PolarSSLTest":0
 
 Parse RSA Key #37 (PKCS#8 encrypted SHA1-RC4-128 DER, 4096-bit)
-depends_on:MBEDTLS_DES_C:MBEDTLS_SHA1_C:MBEDTLS_PKCS12_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA1_C:MBEDTLS_PKCS12_C:MBEDTLS_CIPHER_MODE_CBC
 pk_parse_keyfile_rsa:"data_files/rsa_pkcs8_pbe_sha1_4096_rc4_128.der":"PolarSSLTest":0
 
 Parse RSA Key #38 (PKCS#8 encrypted v2 PBKDF2 3DES)
@@ -1033,11 +1033,11 @@
 pk_parse_keyfile_ec:"data_files/ec_prv.pk8param.pem":"NULL":0
 
 Parse EC Key #6 (PKCS8 encrypted DER)
-depends_on:MBEDTLS_DES_C:MBEDTLS_SHA1_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA1_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 pk_parse_keyfile_ec:"data_files/ec_prv.pk8.pw.der":"polar":0
 
 Parse EC Key #7 (PKCS8 encrypted PEM)
-depends_on:MBEDTLS_DES_C:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 pk_parse_keyfile_ec:"data_files/ec_prv.pk8.pw.pem":"polar":0
 
 Parse EC Key #8 (SEC1 PEM, secp224r1)
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 7631791..402c8b8 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.11.0"
+check_compiletime_version:"2.12.0"
 
 Check runtime library version
-check_runtime_version:"2.11.0"
+check_runtime_version:"2.12.0"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 737556a..73c92bd 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -159,6 +159,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" />

@@ -189,6 +191,7 @@
     <ClInclude Include="..\..\include\mbedtls\memory_buffer_alloc.h" />

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

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

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

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

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

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

@@ -200,6 +203,7 @@
     <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" />

@@ -234,6 +238,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" />

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

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

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

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

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

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

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

@@ -272,6 +279,7 @@
     <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" />