Merge remote-tracking branch 'public/pr/1832' into development
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/ChangeLog b/ChangeLog
index 44533d2..49b6ec7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,8 +4,18 @@
 
 Features
    * Add new crypto primitives from RFC 7539: stream cipher Chacha20, one-time
-   authenticator Poly1305 and AEAD construct Chacha20-Poly1305. Contributed by
-   Daniel King (#485).
+     authenticator Poly1305 and AEAD construct Chacha20-Poly1305. Contributed
+     by Daniel King (#485).
+   * 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's 3394 and 5649.
 
 Bugfix
    * Fix the key_app_writer example which was writing a leading zero byte which
@@ -18,10 +28,42 @@
      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.
+   * 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
+   * 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.
+   * 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.
+   * 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
+   * 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
    * 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
 
@@ -45,6 +87,8 @@
    * Fix compilation warnings with IAR toolchain, on 32 bit platform.
      Reported by rahmanih in #683
    * Fix braces in mbedtls_memory_buffer_alloc_status(). Found by sbranden, #552.
+   * Added length checks to some TLS parsing functions. Found and fixed by
+     Philippe Antoine from Catena cyber. #1663.
 
 Changes
    * Changed CMake defaults for IAR to treat all compiler warnings as errors.
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/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/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 a1f4738..ea0ce98 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -45,7 +45,7 @@
 #define MBEDTLS_CIPHER_MODE_WITH_PADDING
 #endif
 
-#if defined(MBEDTLS_ARC4_C)
+#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
 #define MBEDTLS_CIPHER_MODE_STREAM
 #endif
 
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 e13026e..70820be 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -308,6 +308,7 @@
 //#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
@@ -2249,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.
@@ -2951,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 */
@@ -3028,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/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/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/ssl.h b/include/mbedtls/ssl.h
index 39b7f29..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()
  */
@@ -3023,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/library/CMakeLists.txt b/library/CMakeLists.txt
index 75cc9a0..70fff52 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -40,6 +40,7 @@
     md5.c
     md_wrap.c
     memory_buffer_alloc.c
+    nist_kw.c
     oid.c
     padlock.c
     pem.c
@@ -108,6 +109,10 @@
     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)
diff --git a/library/Makefile b/library/Makefile
index b1597e0..ac88d4c 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -76,11 +76,11 @@
 		hkdf.o						\
 		hmac_drbg.o	md.o		md2.o		\
 		md4.o		md5.o		md_wrap.o	\
-		memory_buffer_alloc.o		oid.o		\
-		padlock.o	pem.o		pk.o		\
-		pk_wrap.o	pkcs12.o	pkcs5.o		\
-		pkparse.o	pkwrite.o	platform.o	\
-		platform_util.o	poly1305.o			\
+		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	\
diff --git a/library/cipher.c b/library/cipher.c
index a913913..7ae6c4a 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -65,11 +65,6 @@
 #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
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/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/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/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
index 2e9a0fd..59cdc7a 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 e537f9d..ba59c48 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;
 
@@ -1247,14 +1247,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 )
@@ -2117,7 +2117,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 );
@@ -2160,7 +2160,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 );
@@ -2709,7 +2709,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,
@@ -2926,7 +2926,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" ) );
@@ -2962,7 +2962,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" ) );
@@ -2991,7 +2991,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 )
             {
@@ -3032,7 +3032,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 0ccab58..52087ae 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 );
@@ -2638,7 +2663,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;
 
@@ -2839,7 +2864,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 );
@@ -2893,7 +2918,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 )
         {
@@ -3020,7 +3045,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 );
@@ -3437,6 +3462,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 ) )
         {
@@ -4171,7 +4200,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 bc63c6e..f1856e2 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;
@@ -1297,11 +1324,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 +1421,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 +1448,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 +1658,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 +1707,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 +1741,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 +1751,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 +1905,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 +1979,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 );
             }
@@ -2053,6 +2133,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 +2167,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 +2217,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 +2226,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 +2264,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 +2274,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 +2349,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 +2435,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 +2889,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 +3107,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 +3211,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 +3587,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 +3684,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 +3778,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 +3794,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 +3807,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 +3855,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 +4187,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 +4426,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 +4629,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 +5769,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 +5886,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 )
@@ -6100,7 +6213,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 +6514,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 +6792,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;
@@ -7249,7 +7362,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 )
     {
@@ -7562,20 +7675,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 b613546..777b603 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -126,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 */
@@ -618,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 */
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/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 5f7d2dd..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"
@@ -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/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 df5634d..f923a43 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -57,6 +57,7 @@
 #include "mbedtls/ecp.h"
 #include "mbedtls/ecjpake.h"
 #include "mbedtls/timing.h"
+#include "mbedtls/nist_kw.h"
 
 #include <string.h>
 
@@ -208,6 +209,9 @@
 #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
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/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 1377dc6..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})
@@ -96,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)
diff --git a/tests/Makefile b/tests/Makefile
index 281e82c..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
@@ -83,6 +88,7 @@
 	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)	\
@@ -428,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 $@
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 ded43f9..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
@@ -526,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"
@@ -543,8 +575,8 @@
 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
@@ -584,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>'
@@ -640,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"
@@ -650,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"
@@ -700,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"
@@ -965,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/ssl-opt.sh b/tests/ssl-opt.sh
index 9faeb67..a1c7d04 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_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/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index e58a2fb..73c92bd 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -191,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" />

@@ -265,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" />