Merge remote-tracking branch 'public/pr/1182' into development
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b9a0ce0..3538b80 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,8 +8,13 @@
 
 option(UNSAFE_BUILD "Allow unsafe builds. These builds ARE NOT SECURE." OFF)
 
+string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
+string(REGEX MATCH "GNU" CMAKE_COMPILER_IS_GNU "${CMAKE_C_COMPILER_ID}")
+string(REGEX MATCH "IAR" CMAKE_COMPILER_IS_IAR "${CMAKE_C_COMPILER_ID}")
+string(REGEX MATCH "MSVC" CMAKE_COMPILER_IS_MSVC "${CMAKE_C_COMPILER_ID}")
+
 # the test suites currently have compile errors with MSVC
-if(MSVC)
+if(CMAKE_COMPILER_IS_MSVC)
     option(ENABLE_TESTING "Build mbed TLS tests." OFF)
 else()
     option(ENABLE_TESTING "Build mbed TLS tests." ON)
@@ -86,7 +91,7 @@
 
 string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
 
-if(CMAKE_COMPILER_IS_GNUCC)
+if(CMAKE_COMPILER_IS_GNU)
     # some warnings we want are not available with old GCC versions
     # note: starting with CMake 2.8 we could use CMAKE_C_COMPILER_VERSION
     execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
@@ -105,7 +110,7 @@
     set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
     set(CMAKE_C_FLAGS_CHECK       "-Werror -Os")
     set(CMAKE_C_FLAGS_CHECKFULL   "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
-endif(CMAKE_COMPILER_IS_GNUCC)
+endif(CMAKE_COMPILER_IS_GNU)
 
 if(CMAKE_COMPILER_IS_CLANG)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow")
@@ -119,16 +124,20 @@
     set(CMAKE_C_FLAGS_CHECK       "-Werror -Os")
 endif(CMAKE_COMPILER_IS_CLANG)
 
-if(MSVC)
+if(CMAKE_COMPILER_IS_IAR)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts --warnings_are_errors -Ohz")
+endif(CMAKE_COMPILER_IS_IAR)
+
+if(CMAKE_COMPILER_IS_MSVC)
     # Strictest warnings, and treat as errors
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
-endif(MSVC)
+endif(CMAKE_COMPILER_IS_MSVC)
 
 if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
-    if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+    if(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
         set(CMAKE_SHARED_LINKER_FLAGS "--coverage")
-    endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+    endif(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
 endif(CMAKE_BUILD_TYPE STREQUAL "Coverage")
 
 if(LIB_INSTALL_DIR)
diff --git a/ChangeLog b/ChangeLog
index b2605e9..cf520cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 mbed TLS ChangeLog (Sorted per branch, date)
 
+= mbed TLS x.x.x branch released xxxx-xx-xx
+
+Features
+   * Add additional block mode, OFB (Output Feedback), to the AES module and
+     cipher abstraction module.
+   * Implement the HMAC-based extract-and-expand key derivation function
+     (HKDF) per RFC 5869. Contributed by Thomas Fossati.
+   * Add support for the CCM* block cipher mode as defined in IEEE Std. 802.15.4.
+
+Bugfix
+   * Fix the cert_write example to handle certificates signed with elliptic
+     curves as well as RSA. Fixes #777 found by dbedev.
+   * Fix for redefinition of _WIN32_WINNT to avoid overriding a definition
+     used by user applications. Found and fixed by Fabio Alessandrelli.
+
+Changes
+   * Changed CMake defaults for IAR to treat all compiler warnings as errors.
+
 = mbed TLS 2.10.0 branch released 2018-06-06
 
 Features
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index dd5c118..e48981a 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -296,6 +296,56 @@
                     unsigned char *output );
 #endif /*MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/**
+ * \brief       This function performs an AES-OFB (Output Feedback Mode)
+ *              encryption or decryption operation.
+ *
+ *              For OFB, you must set up the context with
+ *              mbedtls_aes_setkey_enc(), regardless of whether you are
+ *              performing an encryption or decryption operation. This is
+ *              because OFB mode uses the same key schedule for encryption and
+ *              decryption.
+ *
+ *              The OFB operation is identical for encryption or decryption,
+ *              therefore no operation mode needs to be specified.
+ *
+ * \note        Upon exit, the content of iv, the Initialisation Vector, is
+ *              updated so that you can call the same function again on the next
+ *              block(s) of data and get the same result as if it was encrypted
+ *              in one call. This allows a "streaming" usage, by initialising
+ *              iv_off to 0 before the first call, and preserving its value
+ *              between calls.
+ *
+ *              For non-streaming use, the iv should be initialised on each call
+ *              to a unique value, and iv_off set to 0 on each call.
+ *
+ *              If you need to retain the contents of the initialisation vector,
+ *              you must either save it manually or use the cipher module
+ *              instead.
+ *
+ * \warning     For the OFB mode, the initialisation vector must be unique
+ *              every encryption operation. Reuse of an initialisation vector
+ *              will compromise security.
+ *
+ * \param ctx      The AES context to use for encryption or decryption.
+ * \param length   The length of the input data.
+ * \param iv_off   The offset in IV (updated after use).
+ * \param iv       The initialization vector (updated after use).
+ * \param input    The buffer holding the input data.
+ * \param output   The buffer holding the output data.
+ *
+ * \return         \c 0 on success.
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+                       size_t length,
+                       size_t *iv_off,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output );
+
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 /**
  * \brief      This function performs an AES-CTR encryption or decryption
diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h
index 8585ce5..5d727e7 100644
--- a/include/mbedtls/ccm.h
+++ b/include/mbedtls/ccm.h
@@ -14,6 +14,18 @@
  * <li>Nonce - A unique value that is assigned to the payload and the
  * associated data.</li></ul>
  *
+ * Definition of CCM:
+ * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+ * RFC 3610 "Counter with CBC-MAC (CCM)"
+ *
+ * Related:
+ * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
+ *
+ * Definition of CCM*:
+ * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks
+ * Integer representation is fixed most-significant-octet-first order and
+ * the representation of octets is most-significant-bit-first order. This is
+ * consistent with RFC 3610.
  */
 /*
  *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
@@ -102,7 +114,6 @@
 /**
  * \brief           This function encrypts a buffer using CCM.
  *
- *
  * \note            The tag is written to a separate buffer. To concatenate
  *                  the \p tag with the \p output, as done in <em>RFC-3610:
  *                  Counter with CBC-MAC (CCM)</em>, use
@@ -112,15 +123,17 @@
  * \param ctx       The CCM context to use for encryption.
  * \param length    The length of the input data in Bytes.
  * \param iv        Initialization vector (nonce).
- * \param iv_len    The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ *                  or 13. The length L of the message length field is
+ *                  15 - \p iv_len.
  * \param add       The additional data field.
  * \param add_len   The length of additional data in Bytes.
  *                  Must be less than 2^16 - 2^8.
  * \param input     The buffer holding the input data.
  * \param output    The buffer holding the output data.
  *                  Must be at least \p length Bytes wide.
- * \param tag       The buffer holding the tag.
- * \param tag_len   The length of the tag to generate in Bytes:
+ * \param tag       The buffer holding the authentication field.
+ * \param tag_len   The length of the authentication field to generate in Bytes:
  *                  4, 6, 8, 10, 12, 14 or 16.
  *
  * \return          \c 0 on success.
@@ -133,21 +146,64 @@
                          unsigned char *tag, size_t tag_len );
 
 /**
- * \brief           This function performs a CCM authenticated decryption of a
- *                  buffer.
+ * \brief           This function encrypts a buffer using CCM*.
  *
- * \param ctx       The CCM context to use for decryption.
+ * \note            The tag is written to a separate buffer. To concatenate
+ *                  the \p tag with the \p output, as done in <em>RFC-3610:
+ *                  Counter with CBC-MAC (CCM)</em>, use
+ *                  \p tag = \p output + \p length, and make sure that the
+ *                  output buffer is at least \p length + \p tag_len wide.
+ *
+ * \note            When using this function in a variable tag length context,
+ *                  the tag length has to be encoded into the \p iv passed to
+ *                  this function.
+ *
+ * \param ctx       The CCM context to use for encryption.
  * \param length    The length of the input data in Bytes.
- * \param iv        Initialization vector.
- * \param iv_len    The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param iv        Initialization vector (nonce).
+ * \param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ *                  or 13. The length L of the message length field is
+ *                  15 - \p iv_len.
  * \param add       The additional data field.
  * \param add_len   The length of additional data in Bytes.
  *                  Must be less than 2^16 - 2^8.
  * \param input     The buffer holding the input data.
  * \param output    The buffer holding the output data.
  *                  Must be at least \p length Bytes wide.
- * \param tag       The buffer holding the tag.
- * \param tag_len   The length of the tag in Bytes.
+ * \param tag       The buffer holding the authentication field.
+ * \param tag_len   The length of the authentication field to generate in Bytes:
+ *                  0, 4, 6, 8, 10, 12, 14 or 16.
+ *
+ * \warning         Passing 0 as \p tag_len means that the message is no
+ *                  longer authenticated.
+ *
+ * \return          \c 0 on success.
+ * \return          A CCM or cipher-specific error code on failure.
+ */
+int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output,
+                         unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief           This function performs a CCM authenticated decryption of a
+ *                  buffer.
+ *
+ * \param ctx       The CCM context to use for decryption.
+ * \param length    The length of the input data in Bytes.
+ * \param iv        Initialization vector (nonce).
+ * \param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ *                  or 13. The length L of the message length field is
+ *                  15 - \p iv_len.
+ * \param add       The additional data field.
+ * \param add_len   The length of additional data in Bytes.
+ *                  Must be less than 2^16 - 2^8.
+ * \param input     The buffer holding the input data.
+ * \param output    The buffer holding the output data.
+ *                  Must be at least \p length Bytes wide.
+ * \param tag       The buffer holding the authentication field.
+ * \param tag_len   The length of the authentication field in Bytes.
  *                  4, 6, 8, 10, 12, 14 or 16.
  *
  * \return          \c 0 on success. This indicates that the message is authentic.
@@ -160,6 +216,43 @@
                       const unsigned char *input, unsigned char *output,
                       const unsigned char *tag, size_t tag_len );
 
+/**
+ * \brief           This function performs a CCM* authenticated decryption of a
+ *                  buffer.
+ *
+ * \note            When using this function in a variable tag length context,
+ *                  the tag length has to be decoded from \p iv and passed to
+ *                  this function as \p tag_len. (\p tag needs to be adjusted
+ *                  accordingly.)
+ *
+ * \param ctx       The CCM context to use for decryption.
+ * \param length    The length of the input data in Bytes.
+ * \param iv        Initialization vector (nonce).
+ * \param iv_len    The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ *                  or 13. The length L of the message length field is
+ *                  15 - \p iv_len.
+ * \param add       The additional data field.
+ * \param add_len   The length of additional data in Bytes.
+ *                  Must be less than 2^16 - 2^8.
+ * \param input     The buffer holding the input data.
+ * \param output    The buffer holding the output data.
+ *                  Must be at least \p length Bytes wide.
+ * \param tag       The buffer holding the authentication field.
+ * \param tag_len   The length of the authentication field in Bytes.
+ *                  0, 4, 6, 8, 10, 12, 14 or 16.
+ *
+ * \warning         Passing 0 as \p tag_len means that the message is no
+ *                  longer authenticated.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
+ * \return          A cipher-specific error code on calculation failure.
+ */
+int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      const unsigned char *tag, size_t tag_len );
 
 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
 /**
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index be80332..4689f3a 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -4,7 +4,7 @@
  * \brief Consistency checks for configuration options
  */
 /*
- *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -191,6 +191,10 @@
 #error "MBEDTLS_HAVEGE_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C)
+#error "MBEDTLS_HKDF_C defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C)
 #error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites"
 #endif
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 46b3bdf..cde2fbd 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -164,6 +164,9 @@
     MBEDTLS_CIPHER_ARIA_128_CCM,         /**< Aria cipher with 128-bit key and CCM mode. */
     MBEDTLS_CIPHER_ARIA_192_CCM,         /**< Aria cipher with 192-bit key and CCM mode. */
     MBEDTLS_CIPHER_ARIA_256_CCM,         /**< Aria cipher with 256-bit key and CCM mode. */
+    MBEDTLS_CIPHER_AES_128_OFB,          /**< AES 128-bit cipher in OFB mode. */
+    MBEDTLS_CIPHER_AES_192_OFB,          /**< AES 192-bit cipher in OFB mode. */
+    MBEDTLS_CIPHER_AES_256_OFB,          /**< AES 256-bit cipher in OFB mode. */
 } mbedtls_cipher_type_t;
 
 /** Supported cipher modes. */
@@ -172,7 +175,7 @@
     MBEDTLS_MODE_ECB,                    /**< The ECB cipher mode. */
     MBEDTLS_MODE_CBC,                    /**< The CBC cipher mode. */
     MBEDTLS_MODE_CFB,                    /**< The CFB cipher mode. */
-    MBEDTLS_MODE_OFB,                    /**< The OFB cipher mode - unsupported. */
+    MBEDTLS_MODE_OFB,                    /**< The OFB cipher mode. */
     MBEDTLS_MODE_CTR,                    /**< The CTR cipher mode. */
     MBEDTLS_MODE_GCM,                    /**< The GCM cipher mode. */
     MBEDTLS_MODE_STREAM,                 /**< The stream cipher mode. */
diff --git a/include/mbedtls/cipher_internal.h b/include/mbedtls/cipher_internal.h
index 969ff9c..e02b7f1 100644
--- a/include/mbedtls/cipher_internal.h
+++ b/include/mbedtls/cipher_internal.h
@@ -64,6 +64,14 @@
                      unsigned char *output );
 #endif
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    /** Encrypt using OFB (Full length) */
+    int (*ofb_func)( void *ctx, size_t length, size_t *iv_off,
+                     unsigned char *iv,
+                     const unsigned char *input,
+                     unsigned char *output );
+#endif
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     /** Encrypt using CTR */
     int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index ae10a4d..709f6cf 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -8,7 +8,7 @@
  *  memory footprint.
  */
 /*
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -502,6 +502,13 @@
 #define MBEDTLS_CIPHER_MODE_CBC
 
 /**
+ * \def MBEDTLS_CIPHER_MODE_OFB
+ *
+ * Enable Output Feedback mode (OFB) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_OFB
+
+/**
  * \def MBEDTLS_CIPHER_MODE_CFB
  *
  * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
@@ -2150,6 +2157,21 @@
 //#define MBEDTLS_HAVEGE_C
 
 /**
+ * \def MBEDTLS_HKDF_C
+ *
+ * Enable the HKDF algorithm (RFC 5869).
+ *
+ * Module:  library/hkdf.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the Hashed Message Authentication Code
+ * (HMAC)-based key derivation function (HKDF).
+ */
+#define MBEDTLS_HKDF_C
+
+/**
  * \def MBEDTLS_HMAC_DRBG_C
  *
  * Enable the HMAC_DRBG random generator.
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index a17f8d8..2bde87a 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -4,7 +4,7 @@
  * \brief Error to string translation
  */
 /*
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -89,6 +89,7 @@
  * RSA       4   11
  * ECP       4   9 (Started from top)
  * MD        5   5
+ * HKDF      5   1 (Started from top)
  * CIPHER    6   8
  * SSL       6   17 (Started from top)
  * SSL       7   31
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index bec5577..87535ab 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -113,21 +113,41 @@
  *                  the same as input buffer. If the buffers overlap, the output
  *                  buffer must trail at least 8 Bytes behind the input buffer.
  *
+ * \warning         When this function performs a decryption, it outputs the
+ *                  authentication tag and does not verify that the data is
+ *                  authentic. You should use this function to perform encryption
+ *                  only. For decryption, use mbedtls_gcm_auth_decrypt() instead.
+ *
  * \param ctx       The GCM context to use for encryption or decryption.
- * \param mode      The operation to perform: #MBEDTLS_GCM_ENCRYPT or
- *                  #MBEDTLS_GCM_DECRYPT.
- * \param length    The length of the input data. This must be a multiple of
- *                  16 except in the last call before mbedtls_gcm_finish().
+ * \param mode      The operation to perform:
+ *                  - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption.
+ *                    The ciphertext is written to \p output and the
+ *                    authentication tag is written to \p tag.
+ *                  - #MBEDTLS_GCM_DECRYPT to perform decryption.
+ *                    The plaintext is written to \p output and the
+ *                    authentication tag is written to \p tag.
+ *                    Note that this mode is not recommended, because it does
+ *                    not verify the authenticity of the data. For this reason,
+ *                    you should use mbedtls_gcm_auth_decrypt() instead of
+ *                    calling this function in decryption mode.
+ * \param length    The length of the input data, which is equal to the length
+ *                  of the output data.
  * \param iv        The initialization vector.
  * \param iv_len    The length of the IV.
  * \param add       The buffer holding the additional data.
  * \param add_len   The length of the additional data.
- * \param input     The buffer holding the input data.
- * \param output    The buffer for holding the output data.
+ * \param input     The buffer holding the input data. Its size is \b length.
+ * \param output    The buffer for holding the output data. It must have room
+ *                  for \b length bytes.
  * \param tag_len   The length of the tag to generate.
  * \param tag       The buffer for holding the tag.
  *
- * \return         \c 0 on success.
+ * \return          \c 0 if the encryption or decryption was performed
+ *                  successfully. Note that in #MBEDTLS_GCM_DECRYPT mode,
+ *                  this does not indicate that the data is authentic.
+ * \return          #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid.
+ * \return          #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific
+ *                  error code if the encryption or decryption failed.
  */
 int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
                        int mode,
@@ -150,19 +170,23 @@
  *                  must trail at least 8 Bytes behind the input buffer.
  *
  * \param ctx       The GCM context.
- * \param length    The length of the input data. This must be a multiple
- *                  of 16 except in the last call before mbedtls_gcm_finish().
+ * \param length    The length of the ciphertext to decrypt, which is also
+ *                  the length of the decrypted plaintext.
  * \param iv        The initialization vector.
  * \param iv_len    The length of the IV.
  * \param add       The buffer holding the additional data.
  * \param add_len   The length of the additional data.
- * \param tag       The buffer holding the tag.
- * \param tag_len   The length of the tag.
- * \param input     The buffer holding the input data.
- * \param output    The buffer for holding the output data.
+ * \param tag       The buffer holding the tag to verify.
+ * \param tag_len   The length of the tag to verify.
+ * \param input     The buffer holding the ciphertext. Its size is \b length.
+ * \param output    The buffer for holding the decrypted plaintext. It must
+ *                  have room for \b length bytes.
  *
- * \return         0 if successful and authenticated.
- * \return         #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
+ * \return          \c 0 if successful and authenticated.
+ * \return          #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
+ * \return          #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid.
+ * \return          #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific
+ *                  error code if the decryption failed.
  */
 int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
                       size_t length,
diff --git a/include/mbedtls/hkdf.h b/include/mbedtls/hkdf.h
new file mode 100644
index 0000000..6833e72
--- /dev/null
+++ b/include/mbedtls/hkdf.h
@@ -0,0 +1,125 @@
+/**
+ * \file hkdf.h
+ *
+ * \brief   This file contains the HKDF interface.
+ *
+ *          The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is
+ *          specified by RFC 5869.
+ */
+/*
+ * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_HKDF_H
+#define MBEDTLS_HKDF_H
+
+#include "md.h"
+
+/**
+ *  \name HKDF Error codes
+ *  \{
+ */
+#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA  -0x5F80  /**< Bad input parameters to function. */
+/* \} name */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *  \brief  This is the HMAC-based Extract-and-Expand Key Derivation Function
+ *          (HKDF).
+ *
+ *  \param  md        A hash function; md.size denotes the length of the hash
+ *                    function output in bytes.
+ *  \param  salt      An optional salt value (a non-secret random value);
+ *                    if the salt is not provided, a string of all zeros of
+ *                    md.size length is used as the salt.
+ *  \param  salt_len  The length in bytes of the optional \p salt.
+ *  \param  ikm       The input keying material.
+ *  \param  ikm_len   The length in bytes of \p ikm.
+ *  \param  info      An optional context and application specific information
+ *                    string. This can be a zero-length string.
+ *  \param  info_len  The length of \p info in bytes.
+ *  \param  okm       The output keying material of \p okm_len bytes.
+ *  \param  okm_len   The length of the output keying material in bytes. This
+ *                    must be less than or equal to 255 * md.size bytes.
+ *
+ *  \return 0 on success.
+ *  \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
+ *  \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
+ *          MD layer.
+ */
+int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
+                  size_t salt_len, const unsigned char *ikm, size_t ikm_len,
+                  const unsigned char *info, size_t info_len,
+                  unsigned char *okm, size_t okm_len );
+
+/**
+ *  \brief  Take the input keying material \p ikm and extract from it a
+ *          fixed-length pseudorandom key \p prk.
+ *
+ *  \param       md        A hash function; md.size denotes the length of the
+ *                         hash function output in bytes.
+ *  \param       salt      An optional salt value (a non-secret random value);
+ *                         if the salt is not provided, a string of all zeros
+ *                         of md.size length is used as the salt.
+ *  \param       salt_len  The length in bytes of the optional \p salt.
+ *  \param       ikm       The input keying material.
+ *  \param       ikm_len   The length in bytes of \p ikm.
+ *  \param[out]  prk       A pseudorandom key of at least md.size bytes.
+ *
+ *  \return 0 on success.
+ *  \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
+ *  \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
+ *          MD layer.
+ */
+int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
+                          const unsigned char *salt, size_t salt_len,
+                          const unsigned char *ikm, size_t ikm_len,
+                          unsigned char *prk );
+
+/**
+ *  \brief  Expand the supplied \p prk into several additional pseudorandom
+ *          keys, which is the output of the HKDF.
+ *
+ *  \param  md        A hash function; md.size denotes the length of the hash
+ *                    function output in bytes.
+ *  \param  prk       A pseudorandom key of at least md.size bytes. \p prk is usually,
+ *                    the output from the HKDF extract step.
+ *  \param  prk_len   The length in bytes of \p prk.
+ *  \param  info      An optional context and application specific information
+ *                    string. This can be a zero-length string.
+ *  \param  info_len  The length of \p info in bytes.
+ *  \param  okm       The output keying material of \p okm_len bytes.
+ *  \param  okm_len   The length of the output keying material in bytes. This
+ *                    must be less than or equal to 255 * md.size bytes.
+ *
+ *  \return 0 on success.
+ *  \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
+ *  \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
+ *          MD layer.
+ */
+int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
+                         size_t prk_len, const unsigned char *info,
+                         size_t info_len, unsigned char *okm, size_t okm_len );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* hkdf.h */
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 60b431a..2b5a616 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -630,7 +630,13 @@
     volatile unsigned char diff = 0;
 
     for( i = 0; i < n; i++ )
-        diff |= A[i] ^ B[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 );
 }
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 6e5faa5..60fa7f8 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -30,6 +30,7 @@
     error.c
     gcm.c
     havege.c
+    hkdf.c
     hmac_drbg.c
     md.c
     md2.c
diff --git a/library/Makefile b/library/Makefile
index 25ec374..86696b6 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -57,6 +57,7 @@
 		ecjpake.o	ecp.o				\
 		ecp_curves.o	entropy.o	entropy_poll.o	\
 		error.o		gcm.o		havege.o	\
+		hkdf.o						\
 		hmac_drbg.o	md.o		md2.o		\
 		md4.o		md5.o		md_wrap.o	\
 		memory_buffer_alloc.o		oid.o		\
diff --git a/library/aes.c b/library/aes.c
index fea9b53..4f3351f 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -1061,7 +1061,41 @@
 
     return( 0 );
 }
-#endif /*MBEDTLS_CIPHER_MODE_CFB */
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB (Output Feedback Mode) buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+                           size_t length,
+                           size_t *iv_off,
+                           unsigned char iv[16],
+                           const unsigned char *input,
+                           unsigned char *output )
+{
+    int ret = 0;
+    size_t n = *iv_off;
+
+    while( length-- )
+    {
+        if( n == 0 )
+        {
+            ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            if( ret != 0 )
+                goto exit;
+        }
+        *output++ =  *input++ ^ iv[n];
+
+        n = ( n + 1 ) & 0x0F;
+    }
+
+    *iv_off = n;
+
+exit:
+    return( ret );
+}
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 /*
@@ -1218,6 +1252,72 @@
 };
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB test vectors from:
+ *
+ * https://csrc.nist.gov/publications/detail/sp/800-38a/final
+ */
+static const unsigned char aes_test_ofb_key[3][32] =
+{
+    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_ofb_iv[16] =
+{
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_ofb_pt[64] =
+{
+    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_ofb_ct[3][64] =
+{
+    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+      0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
+      0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+      0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
+      0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+      0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
+      0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },
+    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+      0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
+      0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+      0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f,
+      0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+      0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e,
+      0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a },
+    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+      0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,
+      0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+      0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed,
+      0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+      0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,
+      0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 /*
  * AES-CTR test vectors from:
@@ -1297,7 +1397,8 @@
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     unsigned char prv[16];
 #endif
-#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB)
+#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
+    defined(MBEDTLS_CIPHER_MODE_OFB)
     size_t offset;
 #endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
@@ -1509,6 +1610,69 @@
         mbedtls_printf( "\n" );
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    /*
+     * OFB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        keybits = 128 + u * 64;
+        mode = i & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-OFB-%3d (%s): ", keybits,
+                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  aes_test_ofb_iv, 16 );
+        memcpy( key, aes_test_ofb_key[u], keybits / 8 );
+
+        offset = 0;
+        ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+        /*
+         * AES-192 is an optional feature that may be unavailable when
+         * there is an alternative underlying implementation i.e. when
+         * MBEDTLS_AES_ALT is defined.
+         */
+        if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
+        {
+            mbedtls_printf( "skipped\n" );
+            continue;
+        }
+        else if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+        {
+            memcpy( buf, aes_test_ofb_ct[u], 64 );
+            aes_tests = aes_test_ofb_pt;
+        }
+        else
+        {
+            memcpy( buf, aes_test_ofb_pt, 64 );
+            aes_tests = aes_test_ofb_ct[u];
+        }
+
+        ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf );
+        if( ret != 0 )
+            goto exit;
+
+        if( memcmp( buf, aes_tests, 64 ) != 0 )
+        {
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     /*
      * CTR mode
diff --git a/library/asn1write.c b/library/asn1write.c
index c01c836..72acdf3 100644
--- a/library/asn1write.c
+++ b/library/asn1write.c
@@ -83,7 +83,9 @@
         return( 4 );
     }
 
+#if SIZE_MAX > 0xFFFFFFFF
     if( len <= 0xFFFFFFFF )
+#endif
     {
         if( *p - start < 5 )
             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
@@ -96,7 +98,9 @@
         return( 5 );
     }
 
+#if SIZE_MAX > 0xFFFFFFFF
     return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+#endif
 }
 
 int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
diff --git a/library/ccm.c b/library/ccm.c
index cf65209..804eaf8 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -152,8 +152,10 @@
      * Check length requirements: SP800-38C A.1
      * Additional requirement: a < 2^16 - 2^8 to simplify the code.
      * 'length' checked later (when writing it to the first block)
+     *
+     * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
      */
-    if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
+    if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
         return( MBEDTLS_ERR_CCM_BAD_INPUT );
 
     /* Also implies q is within bounds */
@@ -302,7 +304,7 @@
 /*
  * Authenticated encryption
  */
-int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
                          const unsigned char *iv, size_t iv_len,
                          const unsigned char *add, size_t add_len,
                          const unsigned char *input, unsigned char *output,
@@ -312,10 +314,23 @@
                             add, add_len, input, output, tag, tag_len ) );
 }
 
+int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output,
+                         unsigned char *tag, size_t tag_len )
+{
+    if( tag_len == 0 )
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+    return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
+                add_len, input, output, tag, tag_len ) );
+}
+
 /*
  * Authenticated decryption
  */
-int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
                       const unsigned char *iv, size_t iv_len,
                       const unsigned char *add, size_t add_len,
                       const unsigned char *input, unsigned char *output,
@@ -346,6 +361,18 @@
     return( 0 );
 }
 
+int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      const unsigned char *tag, size_t tag_len )
+{
+    if( tag_len == 0 )
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+    return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
+                add_len, input, output, tag, tag_len ) );
+}
 #endif /* !MBEDTLS_CCM_ALT */
 
 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
diff --git a/library/cipher.c b/library/cipher.c
index a5cd61c..2c599e5 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -191,10 +191,11 @@
     ctx->operation = operation;
 
     /*
-     * For CFB and CTR mode always use the encryption key schedule
+     * For OFB, CFB and CTR mode always use the encryption key schedule
      */
     if( MBEDTLS_ENCRYPT == operation ||
         MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
         MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
     {
         return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
@@ -424,6 +425,21 @@
     }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
+    {
+        if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
+                ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
+        {
+            return( ret );
+        }
+
+        *olen = ilen;
+
+        return( 0 );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
     {
@@ -639,6 +655,7 @@
     *olen = 0;
 
     if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
         MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
         MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
         MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index a9ef819..fd6e69c 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -142,6 +142,15 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off,
+        unsigned char *iv, const unsigned char *input, unsigned char *output )
+{
+    return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off,
+                                    iv, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
         unsigned char *nonce_counter, unsigned char *stream_block,
@@ -191,6 +200,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     aes_crypt_cfb128_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    aes_crypt_ofb_wrap,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     aes_crypt_ctr_wrap,
 #endif
@@ -306,6 +318,41 @@
 };
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+static const mbedtls_cipher_info_t aes_128_ofb_info = {
+    MBEDTLS_CIPHER_AES_128_OFB,
+    MBEDTLS_MODE_OFB,
+    128,
+    "AES-128-OFB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_ofb_info = {
+    MBEDTLS_CIPHER_AES_192_OFB,
+    MBEDTLS_MODE_OFB,
+    192,
+    "AES-192-OFB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_ofb_info = {
+    MBEDTLS_CIPHER_AES_256_OFB,
+    MBEDTLS_MODE_OFB,
+    256,
+    "AES-256-OFB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 static const mbedtls_cipher_info_t aes_128_ctr_info = {
     MBEDTLS_CIPHER_AES_128_CTR,
@@ -358,6 +405,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -421,6 +471,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -548,6 +601,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     camellia_crypt_cfb128_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     camellia_crypt_ctr_wrap,
 #endif
@@ -715,6 +771,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -778,6 +837,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -906,6 +968,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     aria_crypt_cfb128_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     aria_crypt_ctr_wrap,
 #endif
@@ -1073,6 +1138,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -1136,6 +1204,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -1312,6 +1383,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -1357,6 +1431,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -1402,6 +1479,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -1511,6 +1591,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     blowfish_crypt_cfb64_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     blowfish_crypt_ctr_wrap,
 #endif
@@ -1621,6 +1704,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -1684,6 +1770,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
@@ -1724,6 +1813,11 @@
     { MBEDTLS_CIPHER_AES_192_CFB128,       &aes_192_cfb128_info },
     { MBEDTLS_CIPHER_AES_256_CFB128,       &aes_256_cfb128_info },
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    { MBEDTLS_CIPHER_AES_128_OFB,          &aes_128_ofb_info },
+    { MBEDTLS_CIPHER_AES_192_OFB,          &aes_192_ofb_info },
+    { MBEDTLS_CIPHER_AES_256_OFB,          &aes_256_ofb_info },
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     { MBEDTLS_CIPHER_AES_128_CTR,          &aes_128_ctr_info },
     { MBEDTLS_CIPHER_AES_192_CTR,          &aes_192_ctr_info },
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 67900c4..fd96258 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -25,13 +25,14 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
+#include <string.h>
+
 #if defined(MBEDTLS_ENTROPY_C)
 
 #include "mbedtls/entropy.h"
 #include "mbedtls/entropy_poll.h"
 
 #if defined(MBEDTLS_TIMING_C)
-#include <string.h>
 #include "mbedtls/timing.h"
 #endif
 #if defined(MBEDTLS_HAVEGE_C)
diff --git a/library/error.c b/library/error.c
index 8818054..5b57c7c 100644
--- a/library/error.c
+++ b/library/error.c
@@ -105,6 +105,10 @@
 #include "mbedtls/gcm.h"
 #endif
 
+#if defined(MBEDTLS_HKDF_C)
+#include "mbedtls/hkdf.h"
+#endif
+
 #if defined(MBEDTLS_HMAC_DRBG_C)
 #include "mbedtls/hmac_drbg.h"
 #endif
@@ -715,6 +719,11 @@
         mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" );
 #endif /* MBEDTLS_GCM_C */
 
+#if defined(MBEDTLS_HKDF_C)
+    if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) )
+        mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" );
+#endif /* MBEDTLS_HKDF_C */
+
 #if defined(MBEDTLS_HMAC_DRBG_C)
     if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) )
         mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
diff --git a/library/hkdf.c b/library/hkdf.c
new file mode 100644
index 0000000..d2e55e8
--- /dev/null
+++ b/library/hkdf.c
@@ -0,0 +1,180 @@
+/*
+ *  HKDF implementation -- RFC 5869
+ *
+ *  Copyright (C) 2016-2018, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_HKDF_C)
+
+#include <string.h>
+#include "mbedtls/hkdf.h"
+#include "mbedtls/platform_util.h"
+
+int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
+                  size_t salt_len, const unsigned char *ikm, size_t ikm_len,
+                  const unsigned char *info, size_t info_len,
+                  unsigned char *okm, size_t okm_len )
+{
+    int ret;
+    unsigned char prk[MBEDTLS_MD_MAX_SIZE];
+
+    ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk );
+
+    if( ret == 0 )
+    {
+        ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ),
+                                   info, info_len, okm, okm_len );
+    }
+
+    mbedtls_platform_zeroize( prk, sizeof( prk ) );
+
+    return( ret );
+}
+
+int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
+                          const unsigned char *salt, size_t salt_len,
+                          const unsigned char *ikm, size_t ikm_len,
+                          unsigned char *prk )
+{
+    unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' };
+
+    if( salt == NULL )
+    {
+        size_t hash_len;
+
+        hash_len = mbedtls_md_get_size( md );
+
+        if( hash_len == 0 )
+        {
+            return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
+        }
+
+        salt = null_salt;
+        salt_len = hash_len;
+    }
+
+    return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) );
+}
+
+int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
+                         size_t prk_len, const unsigned char *info,
+                         size_t info_len, unsigned char *okm, size_t okm_len )
+{
+    size_t hash_len;
+    size_t where = 0;
+    size_t n;
+    size_t t_len = 0;
+    size_t i;
+    int ret = 0;
+    mbedtls_md_context_t ctx;
+    unsigned char t[MBEDTLS_MD_MAX_SIZE];
+
+    if( okm == NULL )
+    {
+        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+    }
+
+    hash_len = mbedtls_md_get_size( md );
+
+    if( prk_len < hash_len || hash_len == 0 )
+    {
+        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+    }
+
+    if( info == NULL )
+    {
+        info = (const unsigned char *) "";
+        info_len = 0;
+    }
+
+    n = okm_len / hash_len;
+
+    if( (okm_len % hash_len) != 0 )
+    {
+        n++;
+    }
+
+    if( n > 255 )
+    {
+        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+    }
+
+    mbedtls_md_init( &ctx );
+
+    if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 )
+    {
+        goto exit;
+    }
+
+    /* RFC 5869 Section 2.3. */
+    for( i = 1; i <= n; i++ )
+    {
+        size_t num_to_copy;
+        unsigned char c = i & 0xff;
+
+        ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len );
+        if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        ret = mbedtls_md_hmac_update( &ctx, t, t_len );
+        if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        ret = mbedtls_md_hmac_update( &ctx, info, info_len );
+        if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        /* The constant concatenated to the end of each t(n) is a single octet.
+         * */
+        ret = mbedtls_md_hmac_update( &ctx, &c, 1 );
+        if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        ret = mbedtls_md_hmac_finish( &ctx, t );
+        if( ret != 0 )
+        {
+            goto exit;
+        }
+
+        num_to_copy = i != n ? hash_len : okm_len - where;
+        memcpy( okm + where, t, num_to_copy );
+        where += hash_len;
+        t_len = hash_len;
+    }
+
+exit:
+    mbedtls_md_free( &ctx );
+    mbedtls_platform_zeroize( t, sizeof( t ) );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_HKDF_C */
diff --git a/library/net_sockets.c b/library/net_sockets.c
index 7b4a423..202da01 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -47,11 +47,12 @@
 
 #define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
 
-#ifdef _WIN32_WINNT
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501)
 #undef _WIN32_WINNT
-#endif
 /* Enables getaddrinfo() & Co */
 #define _WIN32_WINNT 0x0501
+#endif
+
 #include <ws2tcpip.h>
 
 #include <winsock2.h>
diff --git a/library/pkcs5.c b/library/pkcs5.c
index 440a174..f04f0ab 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -249,8 +249,10 @@
     memset( counter, 0, 4 );
     counter[3] = 1;
 
+#if UINT_MAX > 0xFFFFFFFF
     if( iteration_count > 0xFFFFFFFF )
         return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
+#endif
 
     while( key_length )
     {
diff --git a/library/version_features.c b/library/version_features.c
index e8e448f..fa37119 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -249,6 +249,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     "MBEDTLS_CIPHER_MODE_CBC",
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    "MBEDTLS_CIPHER_MODE_OFB",
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     "MBEDTLS_CIPHER_MODE_CFB",
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
@@ -585,6 +588,9 @@
 #if defined(MBEDTLS_HAVEGE_C)
     "MBEDTLS_HAVEGE_C",
 #endif /* MBEDTLS_HAVEGE_C */
+#if defined(MBEDTLS_HKDF_C)
+    "MBEDTLS_HKDF_C",
+#endif /* MBEDTLS_HKDF_C */
 #if defined(MBEDTLS_HMAC_DRBG_C)
     "MBEDTLS_HMAC_DRBG_C",
 #endif /* MBEDTLS_HMAC_DRBG_C */
diff --git a/programs/test/zeroize.c b/programs/test/zeroize.c
index 252438b..29cc0ac 100644
--- a/programs/test/zeroize.c
+++ b/programs/test/zeroize.c
@@ -66,7 +66,7 @@
     char buf[BUFFER_LEN];
     char *p = buf;
     char *end = p + BUFFER_LEN;
-    char c;
+    int c;
 
     if( argc != 2 )
     {
@@ -83,7 +83,7 @@
     }
 
     while( ( c = fgetc( fp ) ) != EOF && p < end - 1 )
-        *p++ = c;
+        *p++ = (char)c;
     *p = '\0';
 
     if( p - buf != 0 )
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 9cc582d..12baf72 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -607,11 +607,7 @@
     //
     if( strlen( opt.issuer_crt ) )
     {
-        if( !mbedtls_pk_can_do( &issuer_crt.pk, MBEDTLS_PK_RSA ) ||
-            mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->N,
-                         &mbedtls_pk_rsa( *issuer_key )->N ) != 0 ||
-            mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->E,
-                         &mbedtls_pk_rsa( *issuer_key )->E ) != 0 )
+        if( mbedtls_pk_check_pair( &issuer_crt.pk, issuer_key ) != 0 )
         {
             mbedtls_printf( " failed\n  !  issuer_key does not match "
                             "issuer certificate\n\n" );
diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl
index 8fe6079..60e5233 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -31,7 +31,7 @@
 
 my @low_level_modules = qw( AES ARC4 ARIA ASN1 BASE64 BIGNUM BLOWFISH
                             CAMELLIA CCM CMAC CTR_DRBG DES
-                            ENTROPY GCM HMAC_DRBG MD2 MD4 MD5
+                            ENTROPY GCM HKDF HMAC_DRBG MD2 MD4 MD5
                             NET OID PADLOCK PBKDF2 RIPEMD160
                             SHA1 SHA256 SHA512 THREADING XTEA );
 my @high_level_modules = qw( CIPHER DHM ECP MD
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index fa7ee01..653687b 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -82,6 +82,7 @@
 add_test_suite(gcm gcm.aes192_de)
 add_test_suite(gcm gcm.aes256_de)
 add_test_suite(gcm gcm.camellia)
+add_test_suite(hkdf)
 add_test_suite(hmac_drbg hmac_drbg.misc)
 add_test_suite(hmac_drbg hmac_drbg.no_reseed)
 add_test_suite(hmac_drbg hmac_drbg.nopr)
diff --git a/tests/Makefile b/tests/Makefile
index 8efecf3..caacb12 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -46,7 +46,8 @@
 endif
 
 APPS =	test_suite_aes.ecb$(EXEXT)	test_suite_aes.cbc$(EXEXT)	\
-	test_suite_aes.cfb$(EXEXT)	test_suite_aes.rest$(EXEXT)	\
+	test_suite_aes.cfb$(EXEXT)	test_suite_aes.ofb$(EXEXT)	\
+	test_suite_aes.rest$(EXEXT)	\
 	test_suite_arc4$(EXEXT)		test_suite_asn1write$(EXEXT)	\
 	test_suite_base64$(EXEXT)	test_suite_blowfish$(EXEXT)	\
 	test_suite_camellia$(EXEXT)	test_suite_ccm$(EXEXT)		\
@@ -71,6 +72,7 @@
 	test_suite_gcm.aes192_en$(EXEXT)				\
 	test_suite_gcm.aes256_en$(EXEXT)				\
 	test_suite_gcm.camellia$(EXEXT)					\
+	test_suite_hkdf$(EXEXT)						\
 	test_suite_hmac_drbg.misc$(EXEXT)				\
 	test_suite_hmac_drbg.no_reseed$(EXEXT)				\
 	test_suite_hmac_drbg.nopr$(EXEXT)				\
@@ -110,6 +112,10 @@
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_aes test_suite_aes.cfb
 
+test_suite_aes.ofb.c : suites/test_suite_aes.function suites/test_suite_aes.ofb.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo "  Gen   $@"
+	perl scripts/generate_code.pl suites test_suite_aes test_suite_aes.ofb
+
 test_suite_aes.rest.c : suites/test_suite_aes.function suites/test_suite_aes.rest.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_aes test_suite_aes.rest
@@ -178,6 +184,10 @@
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_gcm test_suite_gcm.camellia
 
+test_suite_hkdf.c : suites/test_suite_hkdf.function suites/test_suite_hkdf.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo "  Gen   $@"
+	perl scripts/generate_code.pl suites test_suite_hkdf test_suite_hkdf
+
 test_suite_hmac_drbg.misc.c : suites/test_suite_hmac_drbg.function suites/test_suite_hmac_drbg.misc.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
 	echo "  Gen   $@"
 	perl scripts/generate_code.pl suites test_suite_hmac_drbg test_suite_hmac_drbg.misc
@@ -210,6 +220,10 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test_suite_aes.ofb$(EXEXT): test_suite_aes.ofb.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test_suite_aes.rest$(EXEXT): test_suite_aes.rest.c $(DEP)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -342,6 +356,10 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test_suite_hkdf$(EXEXT): test_suite_hkdf.c $(DEP)
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test_suite_hmac_drbg.misc$(EXEXT): test_suite_hmac_drbg.misc.c $(DEP)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $<	$(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/tests/suites/test_suite_aes.function b/tests/suites/test_suite_aes.function
index c5f0eaa..f1e9033 100644
--- a/tests/suites/test_suite_aes.function
+++ b/tests/suites/test_suite_aes.function
@@ -289,6 +289,63 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_OFB */
+void aes_encrypt_ofb( int fragment_size, char *hex_key_string,
+                      char *hex_iv_string, char *hex_src_string,
+                      char *hex_dst_string )
+{
+    unsigned char key_str[32];
+    unsigned char iv_str[16];
+    unsigned char src_str[64];
+    unsigned char dst_str[64];
+    unsigned char output[32];
+    mbedtls_aes_context ctx;
+    size_t iv_offset = 0;
+    int in_buffer_len;
+    unsigned char* src_str_next;
+    int key_len;
+
+    memset( key_str, 0x00, sizeof( key_str ) );
+    memset( iv_str, 0x00, sizeof( iv_str ) );
+    memset( src_str, 0x00, sizeof( src_str ) );
+    memset( dst_str, 0x00, sizeof( dst_str ) );
+    memset( output, 0x00, sizeof( output ) );
+    mbedtls_aes_init( &ctx );
+
+    TEST_ASSERT( strlen( hex_key_string ) <= ( 32 * 2 ) );
+    TEST_ASSERT( strlen( hex_iv_string ) <= ( 16 * 2 ) );
+    TEST_ASSERT( strlen( hex_src_string ) <= ( 64 * 2 ) );
+    TEST_ASSERT( strlen( hex_dst_string ) <= ( 64 * 2 ) );
+
+    key_len = unhexify( key_str, hex_key_string );
+    unhexify( iv_str, hex_iv_string );
+    in_buffer_len = unhexify( src_str, hex_src_string );
+
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str, key_len * 8 ) == 0 );
+    src_str_next = src_str;
+
+    while( in_buffer_len > 0 )
+    {
+        TEST_ASSERT( mbedtls_aes_crypt_ofb( &ctx, fragment_size, &iv_offset,
+                                            iv_str, src_str_next, output ) == 0 );
+
+        hexify( dst_str, output, fragment_size );
+        TEST_ASSERT( strncmp( (char *) dst_str, hex_dst_string,
+                              ( 2 * fragment_size ) ) == 0 );
+
+        in_buffer_len -= fragment_size;
+        hex_dst_string += ( fragment_size * 2 );
+        src_str_next += fragment_size;
+
+        if( in_buffer_len < fragment_size )
+            fragment_size = in_buffer_len;
+    }
+
+exit:
+    mbedtls_aes_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
 void aes_selftest()
 {
diff --git a/tests/suites/test_suite_aes.ofb.data b/tests/suites/test_suite_aes.ofb.data
new file mode 100644
index 0000000..4b9d80e
--- /dev/null
+++ b/tests/suites/test_suite_aes.ofb.data
@@ -0,0 +1,35 @@
+# NIST Special Publication 800-38A
+# Recommendation for Block Cipher Modes of Operation
+# Test Vectors - Appendix F, Section F.4
+OFB-AES128.Encrypt - Single block
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"2b7e151628aed2a6abf7158809cf4f3c":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172a":"3b3fd92eb72dad20333449f8e83cfb4a"
+
+OFB-AES128.Encrypt - Partial blocks - 7 bytes
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:5:"2b7e151628aed2a6abf7158809cf4f3c":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":"3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e"
+
+OFB-AES128.Encrypt - Test NIST SP800-38A - F.4.1
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"2b7e151628aed2a6abf7158809cf4f3c":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":"3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e"
+
+OFB-AES128.Decrypt - Test NIST SP800-38A - F.4.2
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"2b7e151628aed2a6abf7158809cf4f3c":"000102030405060708090a0b0c0d0e0f":"3b3fd92eb72dad20333449f8e83cfb4a7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
+
+OFB-AES192.Encrypt - Test NIST SP800-38A - F.4.3
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":"cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a"
+
+OFB-AES192.Decrypt - Test NIST SP800-38A - F.4.4
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b":"000102030405060708090a0b0c0d0e0f":"cdc80d6fddf18cab34c25909c99a4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
+
+OFB-AES256.Encrypt - Test NIST SP800-38A - F.4.5
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4":"000102030405060708090a0b0c0d0e0f":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710":"dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484"
+
+OFB-AES256.Decrypt - Test NIST SP800-38A - F.4.6
+depends_on:MBEDTLS_CIPHER_MODE_OFB
+aes_encrypt_ofb:16:"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4":"000102030405060708090a0b0c0d0e0f":"dc7e84bfda79164b7ecd8486985d38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484":"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
+
diff --git a/tests/suites/test_suite_ccm.data b/tests/suites/test_suite_ccm.data
index 90ba42d..cad40d5 100644
--- a/tests/suites/test_suite_ccm.data
+++ b/tests/suites/test_suite_ccm.data
@@ -41,6 +41,39 @@
 CCM lengths #8 msg too long for this IV length (2^16, q = 2)
 ccm_lengths:65536:13:5:8:MBEDTLS_ERR_CCM_BAD_INPUT
 
+CCM lengths #9 tag length 0
+ccm_lengths:5:10:5:0:MBEDTLS_ERR_CCM_BAD_INPUT
+
+CCM* fixed tag lengths #1 all OK
+ccm_star_lengths:5:10:5:8:0
+
+CCM* fixed tag lengths #2 all OK - tag length 0
+ccm_star_lengths:5:10:5:0:0
+
+CCM* encrypt and tag #1
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_star_encrypt_and_tag:MBEDTLS_CIPHER_ID_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":"":"ACDE480000000001":"00000005":2:"08D0842143010000000048DEAC020500000055CF000051525354":"223BC1EC841AB553":0
+
+CCM* encrypt and tag #2
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_star_encrypt_and_tag:MBEDTLS_CIPHER_ID_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":"61626364":"ACDE480000000001":"00000005":4:"69DC842143020000000048DEAC010000000048DEAC0405000000":"D43E022B":0
+
+CCM* encrypt and tag #3
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_star_encrypt_and_tag:MBEDTLS_CIPHER_ID_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":"CE":"ACDE480000000001":"00000005":6:"2BDC842143020000000048DEACFFFF010000000048DEAC060500000001":"D84FDE529061F9C6F1":0
+
+CCM* auth decrypt tag #1
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_star_auth_decrypt:MBEDTLS_CIPHER_ID_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":"223BC1EC841AB553":"ACDE480000000001":"00000005":2:"08D0842143010000000048DEAC020500000055CF000051525354":"":0
+
+CCM* auth decrypt tag #2
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_star_auth_decrypt:MBEDTLS_CIPHER_ID_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":"D43E022B":"ACDE480000000001":"00000005":4:"69DC842143020000000048DEAC010000000048DEAC0405000000":"61626364":0
+
+CCM* auth decrypt tag #3
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_star_auth_decrypt:MBEDTLS_CIPHER_ID_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":"D84FDE529061F9C6F1":"ACDE480000000001":"00000005":6:"2BDC842143020000000048DEACFFFF010000000048DEAC060500000001":"CE":0
+
 CCM encrypt and tag RFC 3610 #1
 depends_on:MBEDTLS_AES_C
 mbedtls_ccm_encrypt_and_tag:MBEDTLS_CIPHER_ID_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":"08090A0B0C0D0E0F101112131415161718191A1B1C1D1E":"00000003020100A0A1A2A3A4A5":"0001020304050607":"588C979A61C663D2F066D0C2C0F989806D5F6B61DAC38417E8D12CFDF926E0"
diff --git a/tests/suites/test_suite_ccm.function b/tests/suites/test_suite_ccm.function
index 2f5c77c..58c8569 100644
--- a/tests/suites/test_suite_ccm.function
+++ b/tests/suites/test_suite_ccm.function
@@ -74,6 +74,47 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_AES_C */
+void ccm_star_lengths( int msg_len, int iv_len, int add_len, int tag_len,
+                       int res )
+{
+    mbedtls_ccm_context ctx;
+    unsigned char key[16];
+    unsigned char msg[10];
+    unsigned char iv[14];
+    unsigned char add[10];
+    unsigned char out[10];
+    unsigned char tag[18];
+    int decrypt_ret;
+
+    mbedtls_ccm_init( &ctx );
+
+    memset( key, 0, sizeof( key ) );
+    memset( msg, 0, sizeof( msg ) );
+    memset( iv, 0, sizeof( iv ) );
+    memset( add, 0, sizeof( add ) );
+    memset( out, 0, sizeof( out ) );
+    memset( tag, 0, sizeof( tag ) );
+
+    TEST_ASSERT( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
+                                 key, 8 * sizeof( key ) ) == 0 );
+
+    TEST_ASSERT( mbedtls_ccm_star_encrypt_and_tag( &ctx, msg_len, iv, iv_len,
+                 add, add_len, msg, out, tag, tag_len ) == res );
+
+    decrypt_ret = mbedtls_ccm_star_auth_decrypt( &ctx, msg_len, iv, iv_len, add,
+                  add_len, msg, out, tag, tag_len );
+
+    if( res == 0 && tag_len != 0 )
+        TEST_ASSERT( decrypt_ret == MBEDTLS_ERR_CCM_AUTH_FAILED );
+    else
+        TEST_ASSERT( decrypt_ret == res );
+
+exit:
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void mbedtls_ccm_encrypt_and_tag( int cipher_id,
                           char *key_hex, char *msg_hex,
@@ -187,3 +228,140 @@
     mbedtls_ccm_free( &ctx );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_ccm_star_encrypt_and_tag( int cipher_id,
+                            char *key_hex, char *msg_hex,
+                            char *source_address_hex, char *frame_counter_hex,
+                            int sec_level, char *add_hex,
+                            char *result_hex, int output_ret )
+{
+    unsigned char key[32];
+    unsigned char msg[50];
+    unsigned char iv[13];
+    unsigned char add[32];
+    unsigned char result[50];
+    unsigned char source_address[8];
+    unsigned char frame_counter[4];
+    mbedtls_ccm_context ctx;
+    size_t i, key_len, msg_len, iv_len, add_len, result_len, source_address_len, frame_counter_len, tag_len;
+    int ret;
+
+    mbedtls_ccm_init( &ctx );
+
+    memset( key, 0x00, sizeof( key ) );
+    memset( msg, 0x00, sizeof( msg ) );
+    memset( iv, 0x00, sizeof( iv ) );
+    memset( add, 0x00, sizeof( add ) );
+    memset( result, 0x00, sizeof( result ) );
+    memset( source_address, 0x00, sizeof( source_address ) );
+    memset( frame_counter, 0x00, sizeof( frame_counter ) );
+
+    key_len = unhexify( key, key_hex );
+    msg_len = unhexify( msg, msg_hex );
+    add_len = unhexify( add, add_hex );
+    result_len = unhexify( result, result_hex );
+    source_address_len = unhexify( source_address, source_address_hex );
+    frame_counter_len = unhexify( frame_counter, frame_counter_hex );
+
+    if( sec_level % 4 == 0)
+        tag_len = 0;
+    else
+        tag_len = 1 << ( sec_level % 4 + 1);
+
+    for( i = 0; i < source_address_len; i++ )
+        iv[i] = source_address[i];
+
+    for( i = 0; i < frame_counter_len; i++ )
+        iv[source_address_len + i] = frame_counter[i];
+
+    iv[source_address_len + frame_counter_len] = sec_level;
+    iv_len = sizeof( iv );
+
+    TEST_ASSERT( mbedtls_ccm_setkey( &ctx, cipher_id, key, key_len * 8 ) == 0 );
+
+    ret = mbedtls_ccm_star_encrypt_and_tag( &ctx, msg_len, iv, iv_len,
+                 add, add_len, msg, msg, msg + msg_len, tag_len );
+
+    TEST_ASSERT( ret == output_ret );
+
+    TEST_ASSERT( memcmp( msg, result, result_len ) == 0 );
+
+    /* Check we didn't write past the end */
+    TEST_ASSERT( msg[result_len] == 0 && msg[result_len + 1] == 0 );
+
+exit:
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_ccm_star_auth_decrypt( int cipher_id,
+                            char *key_hex, char *msg_hex,
+                            char *source_address_hex, char *frame_counter_hex,
+                            int sec_level, char *add_hex,
+                            char *result_hex, int output_ret )
+{
+    unsigned char key[32];
+    unsigned char msg[50];
+    unsigned char iv[13];
+    unsigned char add[32];
+    unsigned char tag[16];
+    unsigned char result[50];
+    unsigned char source_address[8];
+    unsigned char frame_counter[4];
+    mbedtls_ccm_context ctx;
+    size_t i, key_len, msg_len, iv_len, add_len, tag_len, result_len, source_address_len, frame_counter_len;
+    int ret;
+
+    mbedtls_ccm_init( &ctx );
+
+    memset( key, 0x00, sizeof( key ) );
+    memset( msg, 0x00, sizeof( msg ) );
+    memset( iv, 0x00, sizeof( iv ) );
+    memset( add, 0x00, sizeof( add ) );
+    memset( result, 0x00, sizeof( result ) );
+    memset( source_address, 0x00, sizeof( source_address ) );
+    memset( frame_counter, 0x00, sizeof( frame_counter ) );
+    memset( tag, 0x00, sizeof( tag ) );
+
+    key_len = unhexify( key, key_hex );
+    msg_len = unhexify( msg, msg_hex );
+    add_len = unhexify( add, add_hex );
+    result_len = unhexify( result, result_hex );
+    source_address_len = unhexify( source_address, source_address_hex );
+    frame_counter_len = unhexify( frame_counter, frame_counter_hex );
+
+    if( sec_level % 4 == 0)
+        tag_len = 0;
+    else
+        tag_len = 1 << ( sec_level % 4 + 1);
+
+    for( i = 0; i < source_address_len; i++ )
+        iv[i] = source_address[i];
+
+    for( i = 0; i < frame_counter_len; i++ )
+        iv[source_address_len + i] = frame_counter[i];
+
+    iv[source_address_len + frame_counter_len] = sec_level;
+    iv_len = sizeof( iv );
+
+    msg_len -= tag_len;
+    memcpy( tag, msg + msg_len, tag_len );
+
+    TEST_ASSERT( mbedtls_ccm_setkey( &ctx, cipher_id, key, key_len * 8 ) == 0 );
+
+    ret = mbedtls_ccm_star_auth_decrypt( &ctx, msg_len, iv, iv_len,
+                 add, add_len, msg, msg, msg + msg_len, tag_len );
+
+    TEST_ASSERT( ret == output_ret );
+
+    TEST_ASSERT( memcmp( msg, result, result_len ) == 0 );
+
+    /* Check we didn't write past the end (where the original tag is) */
+    TEST_ASSERT( memcmp( msg + msg_len, tag, tag_len ) == 0 );
+
+exit:
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data
index e8e9a15..475c91e 100644
--- a/tests/suites/test_suite_cipher.aes.data
+++ b/tests/suites/test_suite_cipher.aes.data
@@ -474,6 +474,318 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CFB
 enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_CFB128:128:16:16:-1:16:16:16:16
 
+AES-128 OFB - Encrypt and decrypt 0 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:0:-1
+
+AES-128 OFB - Encrypt and decrypt 1 byte
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:1:-1
+
+AES-128 OFB - Encrypt and decrypt 2 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:2:-1
+
+AES-128 OFB - Encrypt and decrypt 7 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:7:-1
+
+AES-128 OFB - Encrypt and decrypt 8 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:8:-1
+
+AES-128 OFB - Encrypt and decrypt 9 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:9:-1
+
+AES-128 OFB - Encrypt and decrypt 15 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:15:-1
+
+AES-128 OFB - Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:16:-1
+
+AES-128 OFB - Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:17:-1
+
+AES-128 OFB - Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:31:-1
+
+AES-128 OFB - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:32:-1
+
+AES-128 OFB - Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:33:-1
+
+AES-128 OFB - Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:47:-1
+
+AES-128 OFB - Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:48:-1
+
+AES-128 OFB - Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_OFB:"AES-128-OFB":128:49:-1
+
+AES-128 OFB - Encrypt and decrypt 0 bytes in multiple parts
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:0:0:-1:0:0:0:0
+
+AES-128 OFB - Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:1:0:-1:1:0:1:0
+
+AES-128 OFB - Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:0:1:-1:0:1:0:1
+
+AES-128 OFB - Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:16:0:-1:16:0:16:0
+
+AES-128 OFB - Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:0:16:-1:0:16:0:16
+
+AES-128 OFB - Encrypt and decrypt 16 bytes in multiple parts 3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:1:15:-1:1:15:1:15
+
+AES-128 OFB - Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:15:1:-1:15:1:15:1
+
+AES-128 OFB - Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:15:7:-1:15:7:15:7
+
+AES-128 OFB - Encrypt and decrypt 22 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:16:6:-1:16:6:16:6
+
+AES-128 OFB - Encrypt and decrypt 23 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:17:6:-1:17:6:17:6
+
+AES-128 OFB - Encrypt and decrypt 32 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_128_OFB:128:16:16:-1:16:16:16:16
+
+AES-192 OFB - Encrypt and decrypt 0 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:0:-1
+
+AES-192 OFB - Encrypt and decrypt 1 byte
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:1:-1
+
+AES-192 OFB - Encrypt and decrypt 2 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:2:-1
+
+AES-192 OFB - Encrypt and decrypt 7 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:7:-1
+
+AES-192 OFB - Encrypt and decrypt 8 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:8:-1
+
+AES-192 OFB - Encrypt and decrypt 9 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:9:-1
+
+AES-192 OFB - Encrypt and decrypt 15 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:15:-1
+
+AES-192 OFB - Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:16:-1
+
+AES-192 OFB - Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:17:-1
+
+AES-192 OFB - Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:31:-1
+
+AES-192 OFB - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:32:-1
+
+AES-192 OFB - Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:33:-1
+
+AES-192 OFB - Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:47:-1
+
+AES-192 OFB - Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:48:-1
+
+AES-192 OFB - Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_192_OFB:"AES-192-OFB":192:49:-1
+
+AES-192 OFB - Encrypt and decrypt 0 bytes in multiple parts
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:0:0:-1:0:0:0:0
+
+AES-192 OFB - Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:1:0:-1:1:0:1:0
+
+AES-192 OFB - Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:0:1:-1:0:1:0:1
+
+AES-192 OFB - Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:16:0:-1:16:0:16:0
+
+AES-192 OFB - Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:0:16:-1:0:16:0:16
+
+AES-192 OFB - Encrypt and decrypt 16 bytes in multiple parts 3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:1:15:-1:1:15:1:15
+
+AES-192 OFB - Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:15:1:-1:15:1:15:1
+
+AES-192 OFB - Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:15:7:-1:15:7:15:7
+
+AES-192 OFB - Encrypt and decrypt 22 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:16:6:-1:16:6:16:6
+
+AES-192 OFB - Encrypt and decrypt 23 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:17:6:-1:17:6:17:6
+
+AES-192 OFB - Encrypt and decrypt 32 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_192_OFB:192:16:16:-1:16:16:16:16
+
+AES-256 OFB - Encrypt and decrypt 0 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:0:-1
+
+AES-256 OFB - Encrypt and decrypt 1 byte
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:1:-1
+
+AES-256 OFB - Encrypt and decrypt 2 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:2:-1
+
+AES-256 OFB - Encrypt and decrypt 7 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:7:-1
+
+AES-256 OFB - Encrypt and decrypt 8 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:8:-1
+
+AES-256 OFB - Encrypt and decrypt 9 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:9:-1
+
+AES-256 OFB - Encrypt and decrypt 15 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:15:-1
+
+AES-256 OFB - Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:16:-1
+
+AES-256 OFB - Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:17:-1
+
+AES-256 OFB - Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:31:-1
+
+AES-256 OFB - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:32:-1
+
+AES-256 OFB - Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:33:-1
+
+AES-256 OFB - Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:47:-1
+
+AES-256 OFB - Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:48:-1
+
+AES-256 OFB - Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_OFB:"AES-256-OFB":256:49:-1
+
+AES-256 OFB - Encrypt and decrypt 0 bytes in multiple parts
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:0:0:-1:0:0:0:0
+
+AES-256 OFB - Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:1:0:-1:1:0:1:0
+
+AES-256 OFB - Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:0:1:-1:0:1:0:1
+
+AES-256 OFB - Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:16:0:-1:16:0:16:0
+
+AES-256 OFB - Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:0:16:-1:0:16:0:16
+
+AES-256 OFB - Encrypt and decrypt 16 bytes in multiple parts 3
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:1:15:-1:1:15:1:15
+
+AES-256 OFB - Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:15:1:-1:15:1:15:1
+
+AES-256 OFB - Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:15:7:-1:15:7:15:7
+
+AES-256 OFB - Encrypt and decrypt 22 bytes in multiple parts 2
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:16:6:-1:16:6:16:6
+
+AES-256 OFB - Encrypt and decrypt 23 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:17:6:-1:17:6:17:6
+
+AES-256 OFB - Encrypt and decrypt 32 bytes in multiple parts 1
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:16:16:-1:16:16:16:16
+
 AES-128 CTR - Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 enc_dec_buf:MBEDTLS_CIPHER_AES_128_CTR:"AES-128-CTR":128:0:-1
@@ -814,6 +1126,18 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CFB
 decrypt_test_vec:MBEDTLS_CIPHER_AES_256_CFB128:-1:"ffffffffff800000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"be66cfea2fecd6bf0ec7b4352c99bcaa":"00000000000000000000000000000000":"":"":0:0
 
+AES Decrypt test vector #7
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+decrypt_test_vec:MBEDTLS_CIPHER_AES_128_OFB:-1:"2B7E151628AED2A6ABF7158809CF4F3C":"000102030405060708090A0B0C0D0E0F":"3B3FD92EB72DAD20333449F8E83CFB4A7789508d16918f03f53c52dac54ed8259740051e9c5fecf64344f7a82260edcc304c6528f659c77866a510d9c1d6ae5e":"6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710":"":"":0:0:
+
+AES Decrypt test vector #8
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+decrypt_test_vec:MBEDTLS_CIPHER_AES_192_OFB:-1:"8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B":"000102030405060708090A0B0C0D0E0F":"CDC80D6FDDF18CAB34C25909C99A4174fcc28b8d4c63837c09e81700c11004018d9a9aeac0f6596f559c6d4daf59a5f26d9f200857ca6c3e9cac524bd9acc92a":"6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710":"":"":0:0:
+
+AES Decrypt test vector #9
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
+decrypt_test_vec:MBEDTLS_CIPHER_AES_256_OFB:-1:"603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4":"000102030405060708090A0B0C0D0E0F":"DC7E84BFDA79164B7ECD8486985D38604febdc6740d20b3ac88f6ad82a4fb08d71ab47a086e86eedf39d1c5bba97c4080126141d67f37be8538f5a8be740e484":"6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710":"":"":0:0:
+
 AES-128-ECB Encrypt NIST KAT #1
 depends_on:MBEDTLS_AES_C
 test_vec_ecb:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"f34481ec3cc627bacd5dc3fb08f273e6":"0336763e966d92595a567cc9ce537f5e":0
diff --git a/tests/suites/test_suite_hkdf.data b/tests/suites/test_suite_hkdf.data
new file mode 100644
index 0000000..1583736
--- /dev/null
+++ b/tests/suites/test_suite_hkdf.data
@@ -0,0 +1,98 @@
+HKDF extract fails with hash_len of 0
+test_hkdf_extract_ret:0:MBEDTLS_ERR_HKDF_BAD_INPUT_DATA
+
+HKDF expand fails with NULL okm
+test_hkdf_expand_ret:32:32:0:MBEDTLS_ERR_HKDF_BAD_INPUT_DATA
+
+HKDF expand fails with hash_len of 0
+test_hkdf_expand_ret:0:32:32:MBEDTLS_ERR_HKDF_BAD_INPUT_DATA
+
+HKDF expand fails with prk_len < hash_len
+test_hkdf_expand_ret:32:16:32:MBEDTLS_ERR_HKDF_BAD_INPUT_DATA
+
+HKDF expand fails with okm_len / hash_len > 255
+test_hkdf_expand_ret:32:32:8192:MBEDTLS_ERR_HKDF_BAD_INPUT_DATA
+
+HKDF RFC5869 Test Vector #1
+depends_on:MBEDTLS_SHA256_C
+test_hkdf:6:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
+
+HKDF RFC5869 Test Vector #2
+depends_on:MBEDTLS_SHA256_C
+test_hkdf:6:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"
+
+HKDF RFC5869 Test Vector #3
+depends_on:MBEDTLS_SHA256_C
+test_hkdf:6:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"":"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"
+
+HKDF RFC5869 Test Vector #4
+depends_on:MBEDTLS_SHA1_C
+test_hkdf:4:"0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":"085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896"
+
+HKDF RFC5869 Test Vector #5
+depends_on:MBEDTLS_SHA1_C
+test_hkdf:4:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4"
+
+HKDF RFC5869 Test Vector #6
+depends_on:MBEDTLS_SHA1_C
+test_hkdf:4:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"":"0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918"
+
+HKDF RFC5869 Test Vector #7
+depends_on:MBEDTLS_SHA1_C
+test_hkdf:4:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"":"":"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48"
+
+HKDF RFC5869 Test Vector #1 Extract
+depends_on:MBEDTLS_SHA256_C
+test_hkdf_extract:6:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
+
+HKDF RFC5869 Test Vector #2 Extract
+depends_on:MBEDTLS_SHA256_C
+test_hkdf_extract:6:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"
+
+HKDF RFC5869 Test Vector #3 Extract
+depends_on:MBEDTLS_SHA256_C
+test_hkdf_extract:6:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04"
+
+HKDF RFC5869 Test Vector #4 Extract
+depends_on:MBEDTLS_SHA1_C
+test_hkdf_extract:4:"0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243"
+
+HKDF RFC5869 Test Vector #5 Extract
+depends_on:MBEDTLS_SHA1_C
+test_hkdf_extract:4:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"8adae09a2a307059478d309b26c4115a224cfaf6"
+
+HKDF RFC5869 Test Vector #6 Extract
+depends_on:MBEDTLS_SHA1_C
+test_hkdf_extract:4:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"da8c8a73c7fa77288ec6f5e7c297786aa0d32d01"
+
+HKDF RFC5869 Test Vector #7 Extract
+depends_on:MBEDTLS_SHA1_C
+test_hkdf_extract:4:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"":"2adccada18779e7c2077ad2eb19d3f3e731385dd"
+
+HKDF RFC5869 Test Vector #1 Expand
+depends_on:MBEDTLS_SHA256_C
+test_hkdf_expand:6:"f0f1f2f3f4f5f6f7f8f9":"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5":"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
+
+HKDF RFC5869 Test Vector #2 Expand
+depends_on:MBEDTLS_SHA256_C
+test_hkdf_expand:6:"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244":"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"
+
+HKDF RFC5869 Test Vector #3 Expand
+depends_on:MBEDTLS_SHA256_C
+test_hkdf_expand:6:"":"19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04":"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"
+
+HKDF RFC5869 Test Vector #4 Expand
+depends_on:MBEDTLS_SHA1_C
+test_hkdf_expand:4:"f0f1f2f3f4f5f6f7f8f9":"9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243":"085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896"
+
+HKDF RFC5869 Test Vector #5 Expand
+depends_on:MBEDTLS_SHA1_C
+test_hkdf_expand:4:"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"8adae09a2a307059478d309b26c4115a224cfaf6":"0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4"
+
+HKDF RFC5869 Test Vector #6 Expand
+depends_on:MBEDTLS_SHA1_C
+test_hkdf_expand:4:"":"da8c8a73c7fa77288ec6f5e7c297786aa0d32d01":"0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918"
+
+HKDF RFC5869 Test Vector #7 Expand
+depends_on:MBEDTLS_SHA1_C
+test_hkdf_expand:4:"":"2adccada18779e7c2077ad2eb19d3f3e731385dd":"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48"
diff --git a/tests/suites/test_suite_hkdf.function b/tests/suites/test_suite_hkdf.function
new file mode 100644
index 0000000..c85a51a
--- /dev/null
+++ b/tests/suites/test_suite_hkdf.function
@@ -0,0 +1,170 @@
+/* BEGIN_HEADER */
+#include "mbedtls/hkdf.h"
+#include "mbedtls/md_internal.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_HKDF_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void test_hkdf( int md_alg, char *hex_ikm_string, char *hex_salt_string,
+                char *hex_info_string, char *hex_okm_string )
+{
+    int ret;
+    size_t ikm_len, salt_len, info_len, okm_len;
+    unsigned char ikm[1024] = { '\0' };
+    unsigned char salt[1024] = { '\0' };
+    unsigned char info[1024] = { '\0' };
+    unsigned char expected_okm[1024] = { '\0' };
+    unsigned char okm[1024] = { '\0' };
+    unsigned char okm_string[1000] = { '\0' };
+
+    const mbedtls_md_info_t *md = mbedtls_md_info_from_type( md_alg );
+    TEST_ASSERT( md != NULL );
+
+    ikm_len = unhexify( ikm, hex_ikm_string );
+    salt_len = unhexify( salt, hex_salt_string );
+    info_len = unhexify( info, hex_info_string );
+    okm_len = unhexify( expected_okm, hex_okm_string );
+
+    ret = mbedtls_hkdf( md, salt, salt_len, ikm, ikm_len, info, info_len, okm,
+                        okm_len);
+    TEST_ASSERT( ret == 0 );
+
+    // Run hexify on it so that it looks nicer if the assertion fails
+    hexify( okm_string, okm, okm_len );
+    TEST_ASSERT( !strcmp( (char *)okm_string, hex_okm_string ) );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void test_hkdf_extract( int md_alg, char *hex_ikm_string,
+                        char *hex_salt_string, char *hex_prk_string )
+{
+    int ret;
+    unsigned char *ikm = NULL;
+    unsigned char *salt = NULL;
+    unsigned char *prk = NULL;
+    unsigned char *output_prk = NULL;
+    size_t ikm_len, salt_len, prk_len, output_prk_len;
+
+    const mbedtls_md_info_t *md = mbedtls_md_info_from_type( md_alg );
+    TEST_ASSERT( md != NULL );
+
+    output_prk_len = mbedtls_md_get_size( md );
+    output_prk = mbedtls_calloc( 1, output_prk_len );
+
+    ikm = unhexify_alloc( hex_ikm_string, &ikm_len );
+    salt = unhexify_alloc( hex_salt_string, &salt_len );
+    prk = unhexify_alloc( hex_prk_string, &prk_len );
+    TEST_ASSERT( prk_len == output_prk_len );
+
+    ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, output_prk );
+    TEST_ASSERT( ret == 0 );
+
+    TEST_ASSERT( !memcmp( output_prk, prk, prk_len ) );
+
+exit:
+    mbedtls_free(ikm);
+    mbedtls_free(salt);
+    mbedtls_free(prk);
+    mbedtls_free(output_prk);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void test_hkdf_expand( int md_alg, char *hex_info_string,
+                       char *hex_prk_string, char *hex_okm_string )
+{
+    enum { OKM_LEN  = 1024 };
+    int ret;
+    unsigned char *info = NULL;
+    unsigned char *prk = NULL;
+    unsigned char *okm = NULL;
+    unsigned char *output_okm = NULL;
+    size_t info_len, prk_len, okm_len;
+
+    const mbedtls_md_info_t *md = mbedtls_md_info_from_type( md_alg );
+    TEST_ASSERT( md != NULL );
+
+    output_okm = mbedtls_calloc( OKM_LEN, 1 );
+
+    prk = unhexify_alloc( hex_prk_string, &prk_len );
+    info = unhexify_alloc( hex_info_string, &info_len );
+    okm = unhexify_alloc( hex_okm_string, &okm_len );
+    TEST_ASSERT( prk_len == mbedtls_md_get_size( md ) );
+    TEST_ASSERT( okm_len < OKM_LEN );
+
+    ret = mbedtls_hkdf_expand( md, prk, prk_len, info, info_len,
+                               output_okm, OKM_LEN );
+    TEST_ASSERT( ret == 0 );
+    TEST_ASSERT( !memcmp( output_okm, okm, okm_len ) );
+
+exit:
+    mbedtls_free(info);
+    mbedtls_free(prk);
+    mbedtls_free(okm);
+    mbedtls_free(output_okm);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void test_hkdf_extract_ret( int hash_len, int ret )
+{
+    int output_ret;
+    unsigned char *salt = NULL;
+    unsigned char *ikm = NULL;
+    unsigned char *prk = NULL;
+    size_t salt_len, ikm_len;
+    struct mbedtls_md_info_t fake_md_info;
+
+    memset( &fake_md_info, 0, sizeof( fake_md_info ) );
+    fake_md_info.type = MBEDTLS_MD_NONE;
+    fake_md_info.size = hash_len;
+
+    prk = mbedtls_calloc( MBEDTLS_MD_MAX_SIZE, 1 );
+    salt_len = 0;
+    ikm_len = 0;
+
+    output_ret = mbedtls_hkdf_extract( &fake_md_info, salt, salt_len,
+                                       ikm, ikm_len, prk );
+    TEST_ASSERT( output_ret == ret );
+
+exit:
+    mbedtls_free(prk);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void test_hkdf_expand_ret( int hash_len, int prk_len, int okm_len, int ret )
+{
+    int output_ret;
+    unsigned char *info = NULL;
+    unsigned char *prk = NULL;
+    unsigned char *okm = NULL;
+    size_t info_len;
+    struct mbedtls_md_info_t fake_md_info;
+
+    memset( &fake_md_info, 0, sizeof( fake_md_info ) );
+    fake_md_info.type = MBEDTLS_MD_NONE;
+    fake_md_info.size = hash_len;
+
+    info_len = 0;
+
+    if (prk_len > 0)
+        prk = mbedtls_calloc( prk_len, 1 );
+
+    if (okm_len > 0)
+        okm = mbedtls_calloc( okm_len, 1 );
+
+    output_ret = mbedtls_hkdf_expand( &fake_md_info, prk, prk_len,
+                                      info, info_len, okm, okm_len );
+    TEST_ASSERT( output_ret == ret );
+
+exit:
+    mbedtls_free(prk);
+    mbedtls_free(okm);
+}
+/* END_CASE */
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index f93546f..737556a 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -179,6 +179,7 @@
     <ClInclude Include="..\..\include\mbedtls\error.h" />

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

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

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

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

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

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

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

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

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

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

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

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

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