Merge remote-tracking branch 'origin/pr/657' into baremetal
diff --git a/configs/baremetal.h b/configs/baremetal.h
index 8bed9a8..4a67c98 100644
--- a/configs/baremetal.h
+++ b/configs/baremetal.h
@@ -52,6 +52,8 @@
 #define MBEDTLS_SSL_CONF_SINGLE_SIG_HASH_MD_ID MBEDTLS_MD_SHA256
 #define MBEDTLS_SSL_CONF_SINGLE_SIG_HASH_TLS_ID MBEDTLS_SSL_HASH_SHA256
 
+#define MBEDTLS_MD_SINGLE_HASH MBEDTLS_MD_INFO_SHA256
+
 /* Key exchanges */
 #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
@@ -117,6 +119,7 @@
 #define MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID
 #define MBEDTLS_X509_ON_DEMAND_PARSING
 #define MBEDTLS_X509_ALWAYS_FLUSH
+#define MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 #define MBEDTLS_ASN1_PARSE_C
 #define MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
 
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 6807ff3..96340e8 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -786,6 +786,73 @@
 #define MBEDTLS_THREADING_IMPL
 #endif
 
+/* Ensure that precisely one hash is enabled. */
+#if defined(MBEDTLS_MD_SINGLE_HASH)
+
+#if defined(MBEDTLS_SHA256_C)
+#define MBEDTLS_SHA256_ENABLED 1
+#else
+#define MBEDTLS_SHA256_ENABLED 0
+#endif /* MBEDTLS_SHA256_C */
+
+#if defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA256_NO_SHA224)
+#define MBEDTLS_SHA224_ENABLED 1
+#else
+#define MBEDTLS_SHA224_ENABLED 0
+#endif /* MBEDTLS_SHA256_C && !MBEDTLS_SHA256_NO_SHA224 */
+
+#if defined(MBEDTLS_SHA512_C)
+#define MBEDTLS_SHA512_ENABLED 2
+#else
+#define MBEDTLS_SHA512_ENABLED 0
+#endif /* MBEDTLS_SHA512_C */
+
+#if defined(MBEDTLS_SHA1_C)
+#define MBEDTLS_SHA1_ENABLED 1
+#else
+#define MBEDTLS_SHA1_ENABLED 0
+#endif /* MBEDTLS_SHA1_C */
+
+#if defined(MBEDTLS_MD2_C)
+#define MBEDTLS_MD2_ENABLED 1
+#else
+#define MBEDTLS_MD2_ENABLED 0
+#endif /* MBEDTLS_MD2_C */
+
+#if defined(MBEDTLS_MD4_C)
+#define MBEDTLS_MD4_ENABLED 1
+#else
+#define MBEDTLS_MD4_ENABLED 0
+#endif /* MBEDTLS_MD4_C */
+
+#if defined(MBEDTLS_MD5_C)
+#define MBEDTLS_MD5_ENABLED 1
+#else
+#define MBEDTLS_MD5_ENABLED 0
+#endif /* MBEDTLS_MD5_C */
+
+#if defined(MBEDTLS_RIPEMD160_C)
+#define MBEDTLS_RIPEMD160_ENABLED 1
+#else
+#define MBEDTLS_RIPEMD160_ENABLED 0
+#endif /* MBEDTLS_RIPEMD160_C */
+
+#define MBEDTLS_HASHES_ENABLED             \
+     ( MBEDTLS_MD2_ENABLED       +         \
+       MBEDTLS_MD4_ENABLED       +         \
+       MBEDTLS_MD5_ENABLED       +         \
+       MBEDTLS_RIPEMD160_ENABLED +         \
+       MBEDTLS_SHA1_ENABLED      +         \
+       MBEDTLS_SHA256_ENABLED    +         \
+       MBEDTLS_SHA512_ENABLED )
+
+#if MBEDTLS_HASHES_ENABLED != 1
+#error "MBEDTLS_MD_SINGLE_HASH must be used with precisely one hash algorithm enabled."
+#endif
+
+#undef MBEDTLS_HASHES_ENABLED
+#endif /* MBEDTLS_MD_SINGLE_HASH */
+
 #if defined(MBEDTLS_THREADING_ALT)
 #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)
 #error "MBEDTLS_THREADING_ALT defined, but not all prerequisites"
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 8340524..f2daf32 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -2029,6 +2029,17 @@
 //#define MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
 
 /**
+ * \def MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
+ *
+ * Remove support for X.509 certificate verification callbacks.
+ *
+ * Uncomment to save some bytes of code by removing support for X.509
+ * certificate verification callbacks in mbedtls_x509_crt_verify() and
+ * related verification API.
+ */
+//#define MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
+
+/**
  * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT
  *
  * Enable parsing and verification of X.509 certificates, CRLs and CSRS
@@ -3815,6 +3826,20 @@
 //#define MBEDTLS_SSL_CONF_SINGLE_SIG_HASH_MD_ID
 //#define MBEDTLS_SSL_CONF_SINGLE_SIG_HASH_TLS_ID
 
+/* Set this to MBEDTLS_MD_INFO_{DIGEST} support of a single message
+ * digest at compile-time, at the benefit of code-size.
+ *
+ * On highly constrained systems with large control over the configuration of
+ * the connection endpoints, this option can be used to hardcode support for
+ * a single hash algorithm.
+ *
+ * You need to make sure that the corresponding digest algorithm attributes
+ * are defined through macros in md.c. See the definitions
+ * MBEDTLS_MD_INFO_SHA256_XXX for example.
+ *
+ */
+//#define MBEDTLS_MD_SINGLE_HASH MBEDTLS_MD_INFO_SHA256
+
 /* \} SECTION: Compile-time SSL configuration */
 
 /* Target and application specific configurations
diff --git a/include/mbedtls/ecjpake.h b/include/mbedtls/ecjpake.h
index 3d8d02a..00e752b 100644
--- a/include/mbedtls/ecjpake.h
+++ b/include/mbedtls/ecjpake.h
@@ -75,7 +75,7 @@
  */
 typedef struct mbedtls_ecjpake_context
 {
-    const mbedtls_md_info_t *md_info;   /**< Hash to use                    */
+    mbedtls_md_handle_t md_info;        /**< Hash to use                    */
     mbedtls_ecp_group grp;              /**< Elliptic curve                 */
     mbedtls_ecjpake_role role;          /**< Are we client or server?       */
     int point_format;                   /**< Format for point export        */
diff --git a/include/mbedtls/hkdf.h b/include/mbedtls/hkdf.h
index 40ee64e..ebf5e12 100644
--- a/include/mbedtls/hkdf.h
+++ b/include/mbedtls/hkdf.h
@@ -70,7 +70,7 @@
  *  \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,
+int mbedtls_hkdf( mbedtls_md_handle_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 );
@@ -99,7 +99,7 @@
  *  \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
  *          MD layer.
  */
-int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
+int mbedtls_hkdf_extract( mbedtls_md_handle_t md,
                           const unsigned char *salt, size_t salt_len,
                           const unsigned char *ikm, size_t ikm_len,
                           unsigned char *prk );
@@ -130,7 +130,7 @@
  *  \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,
+int mbedtls_hkdf_expand( mbedtls_md_handle_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 );
 
diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h
index f1289cb..ed03854 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -138,7 +138,7 @@
  *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED.
  */
 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
-                    const mbedtls_md_info_t * md_info,
+                    mbedtls_md_handle_t md_info,
                     int (*f_entropy)(void *, unsigned char *, size_t),
                     void *p_entropy,
                     const unsigned char *custom,
@@ -158,7 +158,7 @@
  *                      MBEDTLS_ERR_MD_ALLOC_FAILED.
  */
 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
-                        const mbedtls_md_info_t * md_info,
+                        mbedtls_md_handle_t  md_info,
                         const unsigned char *data, size_t data_len );
 
 /**
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index 69ab21f..3b847b4 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -35,6 +35,11 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
 #define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE                -0x5080  /**< The selected feature is not available. */
 #define MBEDTLS_ERR_MD_BAD_INPUT_DATA                     -0x5100  /**< Bad input parameters to function. */
 #define MBEDTLS_ERR_MD_ALLOC_FAILED                       -0x5180  /**< Failed to allocate memory. */
@@ -80,26 +85,72 @@
 #define MBEDTLS_MD_MAX_BLOCK_SIZE         64
 #endif
 
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+
+#define MBEDTLS_MD_INLINABLE_API
+
 /**
- * Opaque struct defined in md_internal.h.
+ * Opaque struct defined in md.c.
  */
 typedef struct mbedtls_md_info_t mbedtls_md_info_t;
 
+
+typedef struct mbedtls_md_info_t const * mbedtls_md_handle_t;
+#define MBEDTLS_MD_INVALID_HANDLE ( (mbedtls_md_handle_t) NULL )
+
+#else /* !MBEDTLS_MD_SINGLE_HASH */
+
+#define MBEDTLS_MD_INLINABLE_API MBEDTLS_ALWAYS_INLINE static inline
+
+typedef int mbedtls_md_handle_t;
+#define MBEDTLS_MD_INVALID_HANDLE       ( (mbedtls_md_handle_t) 0 )
+#define MBEDTLS_MD_UNIQUE_VALID_HANDLE  ( (mbedtls_md_handle_t) 1 )
+
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
+
+#include "md_internal.h"
+
 /**
  * The generic message-digest context.
  */
 typedef struct mbedtls_md_context_t
 {
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
     /** Information about the associated message digest. */
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
+#endif
 
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
     /** The digest-specific context. */
     void *md_ctx;
 
     /** The HMAC part of the context. */
     void *hmac_ctx;
+#else
+    unsigned char md_ctx[ sizeof( MBEDTLS_MD_INFO_CTX_TYPE(
+                                      MBEDTLS_MD_SINGLE_HASH ) ) ];
+
+    unsigned char hmac_ctx[ 2 * MBEDTLS_MD_INFO_BLOCKSIZE(
+                                      MBEDTLS_MD_SINGLE_HASH ) ];
+
+#endif /* MBEDTLS_MD_SINGLE_HASH */
 } mbedtls_md_context_t;
 
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+static inline mbedtls_md_handle_t mbedtls_md_get_handle(
+    struct mbedtls_md_context_t const *ctx )
+{
+    return( ctx->md_info );
+}
+#else /* !MBEDTLS_MD_SINGLE_HASH */
+static inline mbedtls_md_handle_t mbedtls_md_get_handle(
+    struct mbedtls_md_context_t const *ctx )
+{
+    ((void) ctx);
+    return( MBEDTLS_MD_UNIQUE_VALID_HANDLE );
+}
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
+
 /**
  * \brief           This function returns the list of digests supported by the
  *                  generic digest module.
@@ -120,7 +171,7 @@
  * \return          The message-digest information associated with \p md_name.
  * \return          NULL if the associated message-digest information is not found.
  */
-const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name );
+mbedtls_md_handle_t mbedtls_md_info_from_string( const char *md_name );
 
 /**
  * \brief           This function returns the message-digest information
@@ -131,7 +182,7 @@
  * \return          The message-digest information associated with \p md_type.
  * \return          NULL if the associated message-digest information is not found.
  */
-const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type );
+mbedtls_md_handle_t mbedtls_md_info_from_type( mbedtls_md_type_t md_type );
 
 /**
  * \brief           This function initializes a message-digest context without
@@ -182,7 +233,7 @@
  *                  failure.
  * \return          #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure.
  */
-int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED;
+int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, mbedtls_md_handle_t md_info ) MBEDTLS_DEPRECATED;
 #undef MBEDTLS_DEPRECATED
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 
@@ -205,7 +256,9 @@
  *                  failure.
  * \return          #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure.
  */
-int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac );
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_setup( mbedtls_md_context_t *ctx,
+                                               mbedtls_md_handle_t md_info,
+                                               int hmac );
 
 /**
  * \brief           This function clones the state of an message-digest
@@ -238,7 +291,7 @@
  *
  * \return          The size of the message-digest output in Bytes.
  */
-unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info );
+unsigned char mbedtls_md_get_size( mbedtls_md_handle_t md_info );
 
 /**
  * \brief           This function extracts the message-digest type from the
@@ -249,7 +302,7 @@
  *
  * \return          The type of the message digest.
  */
-mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info );
+mbedtls_md_type_t mbedtls_md_get_type( mbedtls_md_handle_t md_info );
 
 /**
  * \brief           This function extracts the message-digest name from the
@@ -260,7 +313,7 @@
  *
  * \return          The name of the message digest.
  */
-const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info );
+const char *mbedtls_md_get_name( mbedtls_md_handle_t md_info );
 
 /**
  * \brief           This function starts a message-digest computation.
@@ -275,7 +328,7 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
-int mbedtls_md_starts( mbedtls_md_context_t *ctx );
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_starts( mbedtls_md_context_t *ctx );
 
 /**
  * \brief           This function feeds an input buffer into an ongoing
@@ -293,7 +346,9 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
-int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen );
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_update( mbedtls_md_context_t *ctx,
+                                                const unsigned char *input,
+                                                size_t ilen );
 
 /**
  * \brief           This function finishes the digest operation,
@@ -313,7 +368,8 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
-int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output );
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_finish( mbedtls_md_context_t *ctx,
+                                                unsigned char *output );
 
 /**
  * \brief          This function calculates the message-digest of a buffer,
@@ -333,8 +389,11 @@
  * \return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                 failure.
  */
-int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
-        unsigned char *output );
+MBEDTLS_MD_INLINABLE_API int mbedtls_md(
+    mbedtls_md_handle_t md_info,
+    const unsigned char *input,
+    size_t ilen,
+    unsigned char *output );
 
 #if defined(MBEDTLS_FS_IO)
 /**
@@ -354,7 +413,7 @@
  *                 the file pointed by \p path.
  * \return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL.
  */
-int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path,
+int mbedtls_md_file( mbedtls_md_handle_t md_info, const char *path,
                      unsigned char *output );
 #endif /* MBEDTLS_FS_IO */
 
@@ -460,12 +519,167 @@
  * \return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                 failure.
  */
-int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen,
+int mbedtls_md_hmac( mbedtls_md_handle_t md_info, const unsigned char *key, size_t keylen,
                 const unsigned char *input, size_t ilen,
                 unsigned char *output );
 
 /* Internal use */
-int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data );
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_process( mbedtls_md_context_t *ctx,
+                                                 const unsigned char *data );
+
+/*
+ * Internal wrapper functions for those MD API functions which should be
+ * inlined in some but not all configurations. The actual MD API will be
+ * implemented either here or in md.c, and forward to the wrappers.
+ */
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_setup_internal(
+    mbedtls_md_context_t *ctx, mbedtls_md_handle_t md_info, int hmac )
+{
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE || ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+    ctx->md_ctx = mbedtls_md_info_ctx_alloc( md_info );
+    if( ctx->md_ctx == NULL )
+        return( MBEDTLS_ERR_MD_ALLOC_FAILED );
+
+    if( hmac != 0 )
+    {
+        ctx->hmac_ctx = mbedtls_calloc( 2,
+                           mbedtls_md_info_block_size( md_info ) );
+        if( ctx->hmac_ctx == NULL )
+        {
+            mbedtls_md_info_ctx_free( md_info, ctx->md_ctx);
+            return( MBEDTLS_ERR_MD_ALLOC_FAILED );
+        }
+    }
+
+    ctx->md_info = md_info;
+#else
+    ((void) hmac);
+#endif /* MBEDTLS_MD_SINGLE_HASH */
+
+    return( 0 );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_starts_internal(
+    mbedtls_md_context_t *ctx )
+{
+    mbedtls_md_handle_t md_info;
+    if( ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    md_info = mbedtls_md_get_handle( ctx );
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    return( mbedtls_md_info_starts( md_info, ctx->md_ctx ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_update_internal(
+    mbedtls_md_context_t *ctx,
+    const unsigned char *input,
+    size_t ilen )
+{
+    mbedtls_md_handle_t md_info;
+    if( ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    md_info = mbedtls_md_get_handle( ctx );
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    return( mbedtls_md_info_update( md_info, ctx->md_ctx,
+                                    input, ilen ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_finish_internal(
+    mbedtls_md_context_t *ctx, unsigned char *output )
+{
+    mbedtls_md_handle_t md_info;
+    if( ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    md_info = mbedtls_md_get_handle( ctx );
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    return( mbedtls_md_info_finish( md_info, ctx->md_ctx,
+                                    output ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_internal(
+    mbedtls_md_handle_t md_info,
+    const unsigned char *input,
+    size_t ilen,
+    unsigned char *output )
+{
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    return( mbedtls_md_info_digest( md_info, input,
+                                    ilen, output) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_process_internal(
+    mbedtls_md_context_t *ctx, const unsigned char *data )
+{
+    mbedtls_md_handle_t md_info;
+    if( ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    md_info = mbedtls_md_get_handle( ctx );
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    return( mbedtls_md_info_process( md_info, ctx->md_ctx, data ) );
+}
+
+#if defined(MBEDTLS_MD_SINGLE_HASH)
+
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_setup(
+    mbedtls_md_context_t *ctx, mbedtls_md_handle_t md_info, int hmac )
+{
+    return( mbedtls_md_setup_internal( ctx, md_info, hmac ) );
+}
+
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_starts(
+    mbedtls_md_context_t *ctx )
+{
+    return( mbedtls_md_starts_internal( ctx ) );
+}
+
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_update(
+    mbedtls_md_context_t *ctx,
+    const unsigned char *input,
+    size_t ilen )
+{
+    return( mbedtls_md_update_internal( ctx, input, ilen ) );
+}
+
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_finish(
+    mbedtls_md_context_t *ctx, unsigned char *output )
+{
+    return( mbedtls_md_finish_internal( ctx, output ) );
+}
+
+MBEDTLS_MD_INLINABLE_API int mbedtls_md(
+    mbedtls_md_handle_t md_info,
+    const unsigned char *input,
+    size_t ilen,
+    unsigned char *output )
+{
+    return( mbedtls_md_internal( md_info, input, ilen, output ) );
+}
+
+MBEDTLS_MD_INLINABLE_API int mbedtls_md_process(
+    mbedtls_md_context_t *ctx, const unsigned char *data )
+{
+    return( mbedtls_md_process_internal( ctx, data ) );
+}
+
+#endif /* MBEDTLS_MD_SINGLE_HASH */
 
 #ifdef __cplusplus
 }
diff --git a/include/mbedtls/md_internal.h b/include/mbedtls/md_internal.h
index 698477b..84944ee 100644
--- a/include/mbedtls/md_internal.h
+++ b/include/mbedtls/md_internal.h
@@ -1,14 +1,12 @@
-/**
+ /**
  * \file md_internal.h
  *
- * \brief Message digest wrappers.
- *
- * \warning This in an internal header. Do not include directly.
+ * \brief This file contains the generic message-digest wrapper.
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  */
 /*
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -23,27 +21,157 @@
  *  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)
+ *  This file is part of Mbed TLS (https://tls.mbed.org)
  */
-#ifndef MBEDTLS_MD_WRAP_H
-#define MBEDTLS_MD_WRAP_H
 
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
+#ifndef MBEDTLS_MD_INTERNAL_H
+#define MBEDTLS_MD_INTERNAL_H
+
+#if defined(MBEDTLS_MD2_C)
+#include "mbedtls/md2.h"
 #endif
 
-#include "md.h"
+#if defined(MBEDTLS_MD4_C)
+#include "mbedtls/md4.h"
+#endif
+
+#if defined(MBEDTLS_MD5_C)
+#include "mbedtls/md5.h"
+#endif
+
+#if defined(MBEDTLS_RIPEMD160_C)
+#include "mbedtls/ripemd160.h"
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+#include "mbedtls/sha1.h"
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+#include "mbedtls/sha256.h"
+#endif
+
+#if defined(MBEDTLS_SHA512_C)
+#include "mbedtls/sha512.h"
+#endif
+
+#include "mbedtls/platform_util.h"
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_calloc    calloc
+#define mbedtls_free       free
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#define MBEDTLS_MD_WRAPPER MBEDTLS_ALWAYS_INLINE static inline
+
+/*
+ * Message-digest information macro definition
+ */
+
+/* Dummy definition to keep check-names.sh happy - don't uncomment */
+//#define MBEDTLS_MD_INFO_SHA256
+
+/* SHA-256 */
+static inline void mbedtls_md_sha256_init_free_dummy( void* ctx )
+{
+    /* Zero-initialization can be skipped. */
+    ((void) ctx);
+}
+#define MBEDTLS_MD_INFO_SHA256_TYPE         MBEDTLS_MD_SHA256
+#define MBEDTLS_MD_INFO_SHA256_CTX_TYPE     mbedtls_sha256_context
+#if defined(MBEDTLS_MD_SINGLE_HASH) && !defined(MBEDTLS_SHA256_ALT)
+/* mbedtls_md_sha256_init() only zeroizes, which is redundant
+ * because mbedtls_md_context is zeroized in mbedtls_md_init(),
+ * and the mbedtls_sha256_context is embedded in mbedtls_md_context_t. */
+#define MBEDTLS_MD_INFO_SHA256_INIT_FUNC    mbedtls_md_sha256_init_free_dummy
+#else
+#define MBEDTLS_MD_INFO_SHA256_INIT_FUNC    mbedtls_sha256_init
+#endif /* MBEDTLS_MD_SINGLE_HASH && !MBEDTLS_SHA256_ALT */
+#define MBEDTLS_MD_INFO_SHA256_NAME         "SHA256"
+#define MBEDTLS_MD_INFO_SHA256_SIZE         32
+#define MBEDTLS_MD_INFO_SHA256_BLOCKSIZE    64
+#define MBEDTLS_MD_INFO_SHA256_STARTS_FUNC  mbedtls_sha256_starts_wrap
+#define MBEDTLS_MD_INFO_SHA256_UPDATE_FUNC  mbedtls_sha224_update_wrap
+#define MBEDTLS_MD_INFO_SHA256_FINISH_FUNC  mbedtls_sha224_finish_wrap
+#define MBEDTLS_MD_INFO_SHA256_DIGEST_FUNC  mbedtls_sha256_wrap
+#define MBEDTLS_MD_INFO_SHA256_ALLOC_FUNC   mbedtls_sha224_ctx_alloc
+#if defined(MBEDTLS_MD_SINGLE_HASH) && !defined(MBEDTLS_SHA256_ALT)
+/* mbedtls_md_sha256_free() only zeroizes, which is redundant
+ * because mbedtls_md_context is zeroized in mbedtls_md_init(),
+ * and the mbedtls_sha256_context is embedded in mbedtls_md_context_t. */
+#define MBEDTLS_MD_INFO_SHA256_FREE_FUNC    mbedtls_md_sha256_init_free_dummy
+#else
+#define MBEDTLS_MD_INFO_SHA256_FREE_FUNC    mbedtls_sha224_ctx_free
+#endif /* MBEDTLS_MD_SINGLE_HASH && !MBEDTLS_SHA256_ALT */
+#define MBEDTLS_MD_INFO_SHA256_CLONE_FUNC   mbedtls_sha224_clone_wrap
+#define MBEDTLS_MD_INFO_SHA256_PROCESS_FUNC mbedtls_sha224_process_wrap
+
+/*
+ * Helper macros to extract fields from ciphersuites.
+ */
+
+#define MBEDTLS_MD_INFO_CTX_TYPE_T( MD )     MD ## _CTX_TYPE
+#define MBEDTLS_MD_INFO_INIT_FUNC_T( MD )    MD ## _INIT_FUNC
+#define MBEDTLS_MD_INFO_TYPE_T( MD )         MD ## _TYPE
+#define MBEDTLS_MD_INFO_NAME_T( MD )         MD ## _NAME
+#define MBEDTLS_MD_INFO_SIZE_T( MD )         MD ## _SIZE
+#define MBEDTLS_MD_INFO_BLOCKSIZE_T( MD )    MD ## _BLOCKSIZE
+#define MBEDTLS_MD_INFO_STARTS_FUNC_T( MD )  MD ## _STARTS_FUNC
+#define MBEDTLS_MD_INFO_UPDATE_FUNC_T( MD )  MD ## _UPDATE_FUNC
+#define MBEDTLS_MD_INFO_FINISH_FUNC_T( MD )  MD ## _FINISH_FUNC
+#define MBEDTLS_MD_INFO_DIGEST_FUNC_T( MD )  MD ## _DIGEST_FUNC
+#define MBEDTLS_MD_INFO_ALLOC_FUNC_T( MD )   MD ## _ALLOC_FUNC
+#define MBEDTLS_MD_INFO_FREE_FUNC_T( MD )    MD ## _FREE_FUNC
+#define MBEDTLS_MD_INFO_CLONE_FUNC_T( MD )   MD ## _CLONE_FUNC
+#define MBEDTLS_MD_INFO_PROCESS_FUNC_T( MD ) MD ## _PROCESS_FUNC
+
+/* Wrapper around MBEDTLS_MD_INFO_{FIELD}_T() which makes sure that
+ * the argument is macro-expanded before concatenated with the
+ * field name. This allows to call these macros as
+ *    MBEDTLS_MD_INFO_{FIELD}( MBEDTLS_MD_SINGLE_HASH ).
+ * where MBEDTLS_MD_SINGLE_HASH expands to MBEDTLS_MD_INFO_{DIGEST}. */
+#define MBEDTLS_MD_INFO_CTX_TYPE( MD )     MBEDTLS_MD_INFO_CTX_TYPE_T( MD )
+#define MBEDTLS_MD_INFO_INIT_FUNC( MD )    MBEDTLS_MD_INFO_INIT_FUNC_T( MD )
+#define MBEDTLS_MD_INFO_TYPE( MD )         MBEDTLS_MD_INFO_TYPE_T( MD )
+#define MBEDTLS_MD_INFO_NAME( MD )         MBEDTLS_MD_INFO_NAME_T( MD )
+#define MBEDTLS_MD_INFO_SIZE( MD )         MBEDTLS_MD_INFO_SIZE_T( MD )
+#define MBEDTLS_MD_INFO_BLOCKSIZE( MD )    MBEDTLS_MD_INFO_BLOCKSIZE_T( MD )
+#define MBEDTLS_MD_INFO_STARTS_FUNC( MD )  MBEDTLS_MD_INFO_STARTS_FUNC_T( MD )
+#define MBEDTLS_MD_INFO_UPDATE_FUNC( MD )  MBEDTLS_MD_INFO_UPDATE_FUNC_T( MD )
+#define MBEDTLS_MD_INFO_FINISH_FUNC( MD )  MBEDTLS_MD_INFO_FINISH_FUNC_T( MD )
+#define MBEDTLS_MD_INFO_DIGEST_FUNC( MD )  MBEDTLS_MD_INFO_DIGEST_FUNC_T( MD )
+#define MBEDTLS_MD_INFO_ALLOC_FUNC( MD )   MBEDTLS_MD_INFO_ALLOC_FUNC_T( MD )
+#define MBEDTLS_MD_INFO_FREE_FUNC( MD )    MBEDTLS_MD_INFO_FREE_FUNC_T( MD )
+#define MBEDTLS_MD_INFO_CLONE_FUNC( MD )   MBEDTLS_MD_INFO_CLONE_FUNC_T( MD )
+#define MBEDTLS_MD_INFO_PROCESS_FUNC( MD ) MBEDTLS_MD_INFO_PROCESS_FUNC_T( MD )
+
 /**
  * Message digest information.
  * Allows message digest functions to be called in a generic way.
  */
+
+typedef int mbedtls_md_starts_func_t( void *ctx );
+typedef int mbedtls_md_update_func_t( void *ctx,
+                                       const unsigned char *input,
+                                       size_t ilen );
+typedef int mbedtls_md_finish_func_t( void *ctx, unsigned char *output );
+typedef int mbedtls_md_digest_func_t( const unsigned char *input,
+                                       size_t ilen,
+                                       unsigned char *output );
+typedef void* mbedtls_md_ctx_alloc_func_t( void );
+typedef void mbedtls_md_ctx_free_func_t( void *ctx );
+typedef void mbedtls_md_clone_func_t( void *st, const void *src );
+typedef int mbedtls_md_process_func_t( void *ctx,
+                                          const unsigned char *input );
+
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
 struct mbedtls_md_info_t
 {
     /** Digest identifier */
@@ -59,59 +187,672 @@
     int block_size;
 
     /** Digest initialisation function */
-    int (*starts_func)( void *ctx );
+    mbedtls_md_starts_func_t *starts_func;
 
     /** Digest update function */
-    int (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
+    mbedtls_md_update_func_t *update_func;
 
     /** Digest finalisation function */
-    int (*finish_func)( void *ctx, unsigned char *output );
+    mbedtls_md_finish_func_t *finish_func;
 
     /** Generic digest function */
-    int (*digest_func)( const unsigned char *input, size_t ilen,
-                        unsigned char *output );
+    mbedtls_md_digest_func_t *digest_func;
 
     /** Allocate a new context */
-    void * (*ctx_alloc_func)( void );
+    mbedtls_md_ctx_alloc_func_t *ctx_alloc_func;
 
     /** Free the given context */
-    void (*ctx_free_func)( void *ctx );
+    mbedtls_md_ctx_free_func_t *ctx_free_func;
 
     /** Clone state from a context */
-    void (*clone_func)( void *dst, const void *src );
+    mbedtls_md_clone_func_t *clone_func;
 
     /** Internal use only */
-    int (*process_func)( void *ctx, const unsigned char *input );
+    mbedtls_md_process_func_t *process_func;
 };
 
+/**
+ * \brief   This macro builds an instance of ::mbedtls_md_info_t
+ *          from an \c MBEDTLS_MD_INFO_XXX identifier.
+ */
+#define MBEDTLS_MD_INFO( MD )                  \
+    { MBEDTLS_MD_INFO_TYPE( MD ),              \
+      MBEDTLS_MD_INFO_NAME( MD ),              \
+      MBEDTLS_MD_INFO_SIZE( MD ),              \
+      MBEDTLS_MD_INFO_BLOCKSIZE( MD ),         \
+      MBEDTLS_MD_INFO_STARTS_FUNC(  MD ),      \
+      MBEDTLS_MD_INFO_UPDATE_FUNC( MD ),       \
+      MBEDTLS_MD_INFO_FINISH_FUNC( MD ),       \
+      MBEDTLS_MD_INFO_DIGEST_FUNC( MD ),       \
+      MBEDTLS_MD_INFO_ALLOC_FUNC( MD ),        \
+      MBEDTLS_MD_INFO_FREE_FUNC( MD ),         \
+      MBEDTLS_MD_INFO_CLONE_FUNC( MD ),        \
+      MBEDTLS_MD_INFO_PROCESS_FUNC( MD ) }
+
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
+
+/*
+ *
+ * Definitions of MD information structures for various digests.
+ *
+ */
+
+/*
+ * MD-2
+ */
+
 #if defined(MBEDTLS_MD2_C)
-extern const mbedtls_md_info_t mbedtls_md2_info;
-#endif
+
+MBEDTLS_MD_WRAPPER int mbedtls_md2_starts_wrap( void *ctx )
+{
+    return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md2_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
+{
+    return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md2_finish_wrap( void *ctx, unsigned char *output )
+{
+    return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) );
+}
+
+MBEDTLS_MD_WRAPPER void* mbedtls_md2_ctx_alloc( void )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) );
+
+    if( ctx != NULL )
+        mbedtls_md2_init( (mbedtls_md2_context *) ctx );
+
+    return( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_md2_ctx_free( void *ctx )
+{
+    mbedtls_md2_free( (mbedtls_md2_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_md2_clone_wrap( void *dst, const void *src )
+{
+    mbedtls_md2_clone( (mbedtls_md2_context *) dst,
+                 (const mbedtls_md2_context *) src );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md2_process_wrap( void *ctx, const unsigned char *data )
+{
+    ((void) data);
+
+    return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) );
+}
+
+#endif /* MBEDTLS_MD2_C */
+
+/*
+ * MD-4
+ */
+
 #if defined(MBEDTLS_MD4_C)
-extern const mbedtls_md_info_t mbedtls_md4_info;
-#endif
+
+MBEDTLS_MD_WRAPPER int mbedtls_md4_starts_wrap( void *ctx )
+{
+    return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md4_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
+{
+    return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md4_finish_wrap( void *ctx, unsigned char *output )
+{
+    return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) );
+}
+
+MBEDTLS_MD_WRAPPER void* mbedtls_md4_ctx_alloc( void )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) );
+
+    if( ctx != NULL )
+        mbedtls_md4_init( (mbedtls_md4_context *) ctx );
+
+    return( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_md4_ctx_free( void *ctx )
+{
+    mbedtls_md4_free( (mbedtls_md4_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_md4_clone_wrap( void *dst, const void *src )
+{
+    mbedtls_md4_clone( (mbedtls_md4_context *) dst,
+                       (const mbedtls_md4_context *) src );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md4_process_wrap( void *ctx, const unsigned char *data )
+{
+    return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) );
+}
+
+#endif /* MBEDTLS_MD4_C */
+
+/*
+ * MD-5
+ */
+
 #if defined(MBEDTLS_MD5_C)
-extern const mbedtls_md_info_t mbedtls_md5_info;
-#endif
+
+MBEDTLS_MD_WRAPPER int mbedtls_md5_starts_wrap( void *ctx )
+{
+    return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md5_update_wrap( void *ctx, const unsigned char *input,
+                             size_t ilen )
+{
+    return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md5_finish_wrap( void *ctx, unsigned char *output )
+{
+    return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) );
+}
+
+MBEDTLS_MD_WRAPPER void* mbedtls_md5_ctx_alloc( void )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) );
+
+    if( ctx != NULL )
+        mbedtls_md5_init( (mbedtls_md5_context *) ctx );
+
+    return( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_md5_ctx_free( void *ctx )
+{
+    mbedtls_md5_free( (mbedtls_md5_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_md5_clone_wrap( void *dst, const void *src )
+{
+    mbedtls_md5_clone( (mbedtls_md5_context *) dst,
+                       (const mbedtls_md5_context *) src );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_md5_process_wrap( void *ctx, const unsigned char *data )
+{
+    return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) );
+}
+
+#endif /* MBEDTLS_MD5_C */
+
+/*
+ * RIPEMD-160
+ */
+
 #if defined(MBEDTLS_RIPEMD160_C)
-extern const mbedtls_md_info_t mbedtls_ripemd160_info;
-#endif
+
+MBEDTLS_MD_WRAPPER int mbedtls_ripemd160_starts_wrap( void *ctx )
+{
+    return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_ripemd160_update_wrap( void *ctx, const unsigned char *input,
+                                   size_t ilen )
+{
+    return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx,
+                                          input, ilen ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_ripemd160_finish_wrap( void *ctx, unsigned char *output )
+{
+    return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx,
+                                          output ) );
+}
+
+MBEDTLS_MD_WRAPPER void* mbedtls_ripemd160_ctx_alloc( void )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) );
+
+    if( ctx != NULL )
+        mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx );
+
+    return( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_ripemd160_ctx_free( void *ctx )
+{
+    mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_ripemd160_clone_wrap( void *dst, const void *src )
+{
+    mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst,
+                       (const mbedtls_ripemd160_context *) src );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_ripemd160_process_wrap( void *ctx, const unsigned char *data )
+{
+    return( mbedtls_internal_ripemd160_process(
+                                (mbedtls_ripemd160_context *) ctx, data ) );
+}
+
+#endif /* MBEDTLS_RIPEMD160_C */
+
+/*
+ * SHA-1
+ */
+
 #if defined(MBEDTLS_SHA1_C)
-extern const mbedtls_md_info_t mbedtls_sha1_info;
-#endif
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha1_starts_wrap( void *ctx )
+{
+    return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha1_update_wrap( void *ctx, const unsigned char *input,
+                              size_t ilen )
+{
+    return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx,
+                                     input, ilen ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha1_finish_wrap( void *ctx, unsigned char *output )
+{
+    return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) );
+}
+
+MBEDTLS_MD_WRAPPER void* mbedtls_sha1_ctx_alloc( void )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) );
+
+    if( ctx != NULL )
+        mbedtls_sha1_init( (mbedtls_sha1_context *) ctx );
+
+    return( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_sha1_clone_wrap( void *dst, const void *src )
+{
+    mbedtls_sha1_clone( (mbedtls_sha1_context *) dst,
+                  (const mbedtls_sha1_context *) src );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_sha1_ctx_free( void *ctx )
+{
+    mbedtls_sha1_free( (mbedtls_sha1_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha1_process_wrap( void *ctx, const unsigned char *data )
+{
+    return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx,
+                                           data ) );
+}
+
+#endif /* MBEDTLS_SHA1_C */
+
+/*
+ * SHA-224 and SHA-256
+ */
+
 #if defined(MBEDTLS_SHA256_C)
+
 #if !defined(MBEDTLS_SHA256_NO_SHA224)
-extern const mbedtls_md_info_t mbedtls_sha224_info;
-#endif
-extern const mbedtls_md_info_t mbedtls_sha256_info;
-#endif
+MBEDTLS_MD_WRAPPER int mbedtls_sha224_starts_wrap( void *ctx )
+{
+    return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) );
+}
+#endif /* !MBEDTLS_SHA256_NO_SHA224 */
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha224_update_wrap( void *ctx, const unsigned char *input,
+                                size_t ilen )
+{
+    return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx,
+                                       input, ilen ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha224_finish_wrap( void *ctx, unsigned char *output )
+{
+    return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx,
+                                       output ) );
+}
+
+#if !defined(MBEDTLS_SHA256_NO_SHA224)
+MBEDTLS_MD_WRAPPER int mbedtls_sha224_wrap( const unsigned char *input, size_t ilen,
+                        unsigned char *output )
+{
+    return( mbedtls_sha256_ret( input, ilen, output, 1 ) );
+}
+#endif /* !MBEDTLS_SHA256_NO_SHA224 */
+
+MBEDTLS_MD_WRAPPER void* mbedtls_sha224_ctx_alloc( void )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) );
+
+    if( ctx != NULL )
+        mbedtls_sha256_init( (mbedtls_sha256_context *) ctx );
+
+    return( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_sha224_ctx_free( void *ctx )
+{
+    mbedtls_sha256_free( (mbedtls_sha256_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_sha224_clone_wrap( void *dst, const void *src )
+{
+    mbedtls_sha256_clone( (mbedtls_sha256_context *) dst,
+                    (const mbedtls_sha256_context *) src );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha224_process_wrap( void *ctx, const unsigned char *data )
+{
+    return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx,
+                                             data ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha256_starts_wrap( void *ctx )
+{
+    return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha256_wrap( const unsigned char *input, size_t ilen,
+                        unsigned char *output )
+{
+    return( mbedtls_sha256_ret( input, ilen, output, 0 ) );
+}
+
+#endif /* MBEDTLS_SHA256_C */
+
+/*
+ * SHA-384 and SHA-512
+ */
+
 #if defined(MBEDTLS_SHA512_C)
-extern const mbedtls_md_info_t mbedtls_sha384_info;
-extern const mbedtls_md_info_t mbedtls_sha512_info;
-#endif
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha384_starts_wrap( void *ctx )
+{
+    return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha384_update_wrap( void *ctx, const unsigned char *input,
+                               size_t ilen )
+{
+    return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx,
+                                       input, ilen ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha384_finish_wrap( void *ctx, unsigned char *output )
+{
+    return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx,
+                                       output ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha384_wrap( const unsigned char *input, size_t ilen,
+                        unsigned char *output )
+{
+    return( mbedtls_sha512_ret( input, ilen, output, 1 ) );
+}
+
+MBEDTLS_MD_WRAPPER void* mbedtls_sha384_ctx_alloc( void )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) );
+
+    if( ctx != NULL )
+        mbedtls_sha512_init( (mbedtls_sha512_context *) ctx );
+
+    return( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_sha384_ctx_free( void *ctx )
+{
+    mbedtls_sha512_free( (mbedtls_sha512_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+MBEDTLS_MD_WRAPPER void mbedtls_sha384_clone_wrap( void *dst, const void *src )
+{
+    mbedtls_sha512_clone( (mbedtls_sha512_context *) dst,
+                    (const mbedtls_sha512_context *) src );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha384_process_wrap( void *ctx, const unsigned char *data )
+{
+    return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx,
+                                             data ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha512_starts_wrap( void *ctx )
+{
+    return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) );
+}
+
+MBEDTLS_MD_WRAPPER int mbedtls_sha512_wrap( const unsigned char *input, size_t ilen,
+                        unsigned char *output )
+{
+    return( mbedtls_sha512_ret( input, ilen, output, 0 ) );
+}
+
+#endif /* MBEDTLS_SHA512_C */
+
+/*
+ * Getter functions for MD info structure.
+ */
+
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+
+MBEDTLS_ALWAYS_INLINE static inline mbedtls_md_type_t mbedtls_md_info_type(
+    mbedtls_md_handle_t info )
+{
+    return( info->type );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline const char * mbedtls_md_info_name(
+    mbedtls_md_handle_t info )
+{
+    return( info->name );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_size(
+    mbedtls_md_handle_t info )
+{
+    return( info->size );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_block_size(
+    mbedtls_md_handle_t info )
+{
+    return( info->block_size );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_starts(
+    mbedtls_md_handle_t info,
+    void *ctx )
+{
+    return( info->starts_func( ctx ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_update(
+    mbedtls_md_handle_t info,
+    void *ctx,
+    const unsigned char *input,
+    size_t ilen )
+{
+    return( info->update_func( ctx, input, ilen ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_finish(
+    mbedtls_md_handle_t info,
+    void *ctx,
+    unsigned char *output )
+{
+    return( info->finish_func( ctx, output ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_digest(
+    mbedtls_md_handle_t info,
+    const unsigned char *input,
+    size_t ilen,
+    unsigned char *output )
+{
+    return( info->digest_func( input, ilen, output ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline void* mbedtls_md_info_ctx_alloc(
+    mbedtls_md_handle_t info )
+{
+    return( info->ctx_alloc_func() );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline void mbedtls_md_info_ctx_free(
+    mbedtls_md_handle_t info,
+    void *ctx )
+{
+    info->ctx_free_func( ctx );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline void mbedtls_md_info_clone(
+    mbedtls_md_handle_t info,
+    void *dst,
+    const void *src )
+{
+    info->clone_func( dst, src );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_process(
+    mbedtls_md_handle_t info,
+    void *ctx,
+    const unsigned char *input )
+{
+    return( info->process_func( ctx, input ) );
+}
+
+#else /* !MBEDTLS_MD_SINGLE_HASH */
+
+MBEDTLS_ALWAYS_INLINE static inline mbedtls_md_type_t mbedtls_md_info_type(
+    mbedtls_md_handle_t info )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_TYPE( MBEDTLS_MD_SINGLE_HASH ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline const char * mbedtls_md_info_name(
+    mbedtls_md_handle_t info )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_NAME( MBEDTLS_MD_SINGLE_HASH ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_size(
+    mbedtls_md_handle_t info )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_SIZE( MBEDTLS_MD_SINGLE_HASH ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_block_size(
+    mbedtls_md_handle_t info )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_BLOCKSIZE( MBEDTLS_MD_SINGLE_HASH ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_starts(
+    mbedtls_md_handle_t info,
+    void *ctx )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_STARTS_FUNC( MBEDTLS_MD_SINGLE_HASH )( ctx ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_update(
+    mbedtls_md_handle_t info,
+    void *ctx,
+    const unsigned char *input,
+    size_t ilen )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_UPDATE_FUNC( MBEDTLS_MD_SINGLE_HASH )
+            ( ctx, input, ilen ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline void mbedtls_md_info_init(
+    mbedtls_md_handle_t info,
+    void *ctx )
+{
+    ((void) info);
+    MBEDTLS_MD_INFO_INIT_FUNC( MBEDTLS_MD_SINGLE_HASH )( ctx );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_finish(
+    mbedtls_md_handle_t info,
+    void *ctx,
+    unsigned char *output )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_FINISH_FUNC( MBEDTLS_MD_SINGLE_HASH )
+            ( ctx, output ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_digest(
+    mbedtls_md_handle_t info,
+    const unsigned char *input,
+    size_t ilen,
+    unsigned char *output )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_DIGEST_FUNC( MBEDTLS_MD_SINGLE_HASH )
+            ( input, ilen, output ) );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline void* mbedtls_md_info_ctx_alloc(
+    mbedtls_md_handle_t info )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_ALLOC_FUNC( MBEDTLS_MD_SINGLE_HASH )() );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline void mbedtls_md_info_ctx_free(
+    mbedtls_md_handle_t info,
+    void *ctx )
+{
+    ((void) info);
+    MBEDTLS_MD_INFO_FREE_FUNC( MBEDTLS_MD_SINGLE_HASH )( ctx );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline void mbedtls_md_info_clone(
+    mbedtls_md_handle_t info,
+    void *dst,
+    const void *src )
+{
+    ((void) info);
+    MBEDTLS_MD_INFO_CLONE_FUNC( MBEDTLS_MD_SINGLE_HASH )( dst, src );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_md_info_process(
+    mbedtls_md_handle_t info,
+    void *ctx,
+    const unsigned char *input )
+{
+    ((void) info);
+    return( MBEDTLS_MD_INFO_PROCESS_FUNC( MBEDTLS_MD_SINGLE_HASH )
+            ( ctx, input ) );
+}
+
+#endif /* MBEDTLS_MD_SINGLE_HASH */
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* MBEDTLS_MD_WRAP_H */
+#endif /* MBEDTLS_MD_INTERNAL_H */
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index fbb595a..7033af8 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -113,6 +113,12 @@
 
 #endif /* MBEDTLS_CHECK_PARAMS */
 
+#if defined(__GNUC__) || defined(__arm__)
+#define MBEDTLS_ALWAYS_INLINE __attribute__((always_inline))
+#else
+#define MBEDTLS_ALWAYS_INLINE
+#endif
+
 /* Internal helper macros for deprecating API constants. */
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 #if defined(MBEDTLS_DEPRECATED_WARNING)
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 40ad4b1..8008b51 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -142,11 +142,19 @@
 /*
  * Various constants
  */
+#if !defined(MBEDTLS_SSL_PROTO_NO_TLS)
 #define MBEDTLS_SSL_MAJOR_VERSION_3             3
 #define MBEDTLS_SSL_MINOR_VERSION_0             0   /*!< SSL v3.0 */
 #define MBEDTLS_SSL_MINOR_VERSION_1             1   /*!< TLS v1.0 */
 #define MBEDTLS_SSL_MINOR_VERSION_2             2   /*!< TLS v1.1 */
 #define MBEDTLS_SSL_MINOR_VERSION_3             3   /*!< TLS v1.2 */
+#else /* MBEDTLS_SSL_PROTO_NO_TLS */
+#define MBEDTLS_SSL_MAJOR_VERSION_3             254
+#define MBEDTLS_SSL_MINOR_VERSION_0             257   /*!< unused    */
+#define MBEDTLS_SSL_MINOR_VERSION_1             256   /*!< unused    */
+#define MBEDTLS_SSL_MINOR_VERSION_2             255   /*!< DTLS v1.0 */
+#define MBEDTLS_SSL_MINOR_VERSION_3             253   /*!< DTLS v1.2 */
+#endif /* MBEDTLS_SSL_PROTO_NO_TLS */
 
 #define MBEDTLS_SSL_TRANSPORT_STREAM            0   /*!< TLS      */
 #define MBEDTLS_SSL_TRANSPORT_DATAGRAM          1   /*!< DTLS     */
@@ -1033,7 +1041,8 @@
     void *p_sni;                    /*!< context for SNI callback           */
 #endif
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+    !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
     /** Callback to customize X.509 certificate chain verification          */
     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
     void *p_vrfy;                   /*!< context for X.509 verify calllback */
@@ -1165,18 +1174,18 @@
     unsigned int dhm_min_bitlen;    /*!< min. bit length of the DHM prime   */
 #endif
 
-#if !defined(MBEDTLS_SSL_CONF_MAX_MAJOR_VER)
-    unsigned char max_major_ver;    /*!< max. major version used            */
-#endif /* !MBEDTLS_SSL_CONF_MAX_MAJOR_VER */
-#if !defined(MBEDTLS_SSL_CONF_MAX_MINOR_VER)
-    unsigned char max_minor_ver;    /*!< max. minor version used            */
-#endif /* !MBEDTLS_SSL_CONF_MAX_MINOR_VER */
 #if !defined(MBEDTLS_SSL_CONF_MIN_MAJOR_VER)
     unsigned char min_major_ver;    /*!< min. major version used            */
 #endif /* !MBEDTLS_SSL_CONF_MIN_MAJOR_VER */
+#if !defined(MBEDTLS_SSL_CONF_MAX_MAJOR_VER)
+    unsigned char max_major_ver;    /*!< max. major version used            */
+#endif /* !MBEDTLS_SSL_CONF_MAX_MAJOR_VER */
 #if !defined(MBEDTLS_SSL_CONF_MIN_MINOR_VER)
-    unsigned char min_minor_ver;    /*!< min. minor version used            */
+    uint16_t min_minor_ver;    /*!< min. minor version used            */
 #endif /* !MBEDTLS_SSL_CONF_MIN_MINOR_VER */
+#if !defined(MBEDTLS_SSL_CONF_MAX_MINOR_VER)
+    uint16_t max_minor_ver;    /*!< max. minor version used            */
+#endif /* !MBEDTLS_SSL_CONF_MAX_MINOR_VER */
 
     /*
      * Flags (bitfields)
@@ -1588,7 +1597,8 @@
  */
 void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode );
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+    !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
 /**
  * \brief          Set the verification callback (Optional).
  *
@@ -1603,7 +1613,7 @@
 void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf,
                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                      void *p_vrfy );
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 
 #if !defined(MBEDTLS_SSL_CONF_RNG)
 /**
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index d9690cb..a98a458 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -1196,6 +1196,8 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
           MBEDTLS_SSL_PROTO_TLS1_2 */
 
+#if defined(MBEDTLS_SSL_PROTO_TLS)
+
 /*
  * Convert version numbers to/from wire format
  * and, for DTLS, to/from TLS equivalent.
@@ -1257,6 +1259,88 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS */
 }
 
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_ssl_ver_leq( int v0, int v1 )
+{
+    return( v0 <= v1 );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_ssl_ver_lt( int v0, int v1 )
+{
+    return( v0 < v1 );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_ssl_ver_geq( int v0, int v1 )
+{
+    return( v0 >= v1 );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_ssl_ver_gt( int v0, int v1 )
+{
+    return( v0 > v1 );
+}
+
+#else /* MBEDTLS_SSL_PROTO_TLS */
+
+/* If only DTLS is enabled, we can match the internal encoding
+ * with the standard's encoding of versions. */
+static inline void mbedtls_ssl_write_version( int major, int minor,
+                                              int transport,
+                                              unsigned char ver[2] )
+{
+    ((void) transport);
+    ver[0] = (unsigned char) major;
+    ver[1] = (unsigned char) minor;
+}
+
+static inline void mbedtls_ssl_read_version( int *major, int *minor,
+                                             int transport,
+                                             const unsigned char ver[2] )
+{
+    ((void) transport);
+    *major = ver[0];
+    *minor = ver[1];
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_ssl_ver_leq( int v0, int v1 )
+{
+    return( v0 >= v1 );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_ssl_ver_lt( int v0, int v1 )
+{
+    return( v0 > v1 );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_ssl_ver_geq( int v0, int v1 )
+{
+    return( v0 <= v1 );
+}
+
+MBEDTLS_ALWAYS_INLINE static inline int mbedtls_ssl_ver_gt( int v0, int v1 )
+{
+    return( v0 < v1 );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS */
+
+MBEDTLS_ALWAYS_INLINE static inline size_t mbedtls_ssl_minor_ver_index(
+    int ver )
+{
+    switch( ver )
+    {
+        case MBEDTLS_SSL_MINOR_VERSION_0:
+            return( 0 );
+        case MBEDTLS_SSL_MINOR_VERSION_1:
+            return( 1 );
+        case MBEDTLS_SSL_MINOR_VERSION_2:
+            return( 2 );
+        case MBEDTLS_SSL_MINOR_VERSION_3:
+            return( 3 );
+    }
+    return( 0 );
+}
+
 #ifdef __cplusplus
 }
 #endif
@@ -1697,7 +1781,8 @@
 #define MBEDTLS_SSL_BEGIN_FOR_EACH_CIPHERSUITE( ssl, ver, info ) \
     {                                                            \
         int const *__id_ptr;                                     \
-        for( __id_ptr=(ssl)->conf->ciphersuite_list[ (ver) ];    \
+        for( __id_ptr=(ssl)->conf->ciphersuite_list[             \
+                 mbedtls_ssl_minor_ver_index( ver ) ];           \
              *__id_ptr != 0; __id_ptr++ )                        \
         {                                                        \
            const int __id = *__id_ptr;                           \
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 182ab15..662ec68 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -214,6 +214,8 @@
 mbedtls_x509write_cert;
 #endif /* MBEDTLS_X509_CRT_WRITE_C */
 
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+
 /**
  * Item in a verification chain: cert and flags for it
  */
@@ -236,6 +238,16 @@
     unsigned len;
 } mbedtls_x509_crt_verify_chain;
 
+#else /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+
+typedef struct
+{
+    unsigned len;
+    uint32_t flags;
+} mbedtls_x509_crt_verify_chain;
+
+#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 
 /**
@@ -249,6 +261,9 @@
     /* for find_parent_in() */
     mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */
 
+    /* current child CRT */
+    mbedtls_x509_crt *cur_crt;
+
 #if defined(MBEDTLS_HAVE_TIME_DATE)
     mbedtls_x509_crt *fallback_parent;
     int fallback_signature_is_good;
@@ -502,14 +517,17 @@
  *                 verification process.
  */
 int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
-                     mbedtls_x509_crt *trust_ca,
-                     mbedtls_x509_crl *ca_crl,
+                   mbedtls_x509_crt *trust_ca,
+                   mbedtls_x509_crl *ca_crl,
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION) || defined(DOXYGEN_ONLY)
-                     const char *cn,
-#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION || defined(DOXYGEN_ONLY) */
-                     uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy );
+                   const char *cn,
+#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION || DOXYGEN_ONLY */
+                   uint32_t *flags
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK) || defined(DOXYGEN_ONLY)
+                   , int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                   void *p_vrfy
+#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK || DOXYGEN_ONLY */
+    );
 
 /**
  * \brief          Verify the certificate signature according to profile
@@ -544,10 +562,13 @@
                      const mbedtls_x509_crt_profile *profile,
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION) || defined(DOXYGEN_ONLY)
                      const char *cn,
-#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION || defined(DOXYGEN_ONLY) */
-                     uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy );
+#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION || DOXYGEN_ONLY */
+                     uint32_t *flags
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK) || defined(DOXYGEN_ONLY)
+                     , int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                     void *p_vrfy
+#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK || DOXYGEN_ONLY */
+    );
 
 /**
  * \brief          Restartable version of \c mbedtls_crt_verify_with_profile()
@@ -577,10 +598,12 @@
                      const mbedtls_x509_crt_profile *profile,
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION) || defined(DOXYGEN_ONLY)
                      const char *cn,
-#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION || defined(DOXYGEN_ONLY) */
+#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION || DOXYGEN_ONLY */
                      uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy,
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK) || defined(DOXYGEN_ONLY)
+                   int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                   void *p_vrfy,
+#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK || DOXYGEN_ONLY */
                      mbedtls_x509_crt_restart_ctx *rs_ctx );
 
 #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h
index 37a7ef1..9c53f3e 100644
--- a/include/tinycrypt/ecc.h
+++ b/include/tinycrypt/ecc.h
@@ -1,5 +1,10 @@
 /* ecc.h - TinyCrypt interface to common ECC functions */
 
+/*
+ *  Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved.
+ *  SPDX-License-Identifier: BSD-3-Clause
+ */
+
 /* Copyright (c) 2014, Kenneth MacKay
  * All rights reserved.
  *
diff --git a/include/tinycrypt/ecc_dh.h b/include/tinycrypt/ecc_dh.h
index c680a77..a2edb01 100644
--- a/include/tinycrypt/ecc_dh.h
+++ b/include/tinycrypt/ecc_dh.h
@@ -1,6 +1,11 @@
 /* ecc_dh.h - TinyCrypt interface to EC-DH implementation */
 
 /*
+ *  Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved.
+ *  SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
  * Copyright (c) 2014, Kenneth MacKay
  * All rights reserved.
  *
diff --git a/include/tinycrypt/ecc_dsa.h b/include/tinycrypt/ecc_dsa.h
index cc5eebc..e54a77e 100644
--- a/include/tinycrypt/ecc_dsa.h
+++ b/include/tinycrypt/ecc_dsa.h
@@ -1,6 +1,11 @@
 /* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
 
 /*
+ *  Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved.
+ *  SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
  * Copyright (c) 2014, Kenneth MacKay
  * All rights reserved.
  *
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 461843b..bb975cd 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -38,7 +38,6 @@
     md2.c
     md4.c
     md5.c
-    md_wrap.c
     memory_buffer_alloc.c
     nist_kw.c
     oid.c
diff --git a/library/Makefile b/library/Makefile
index 50faed9..062846b 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -77,7 +77,7 @@
 		error.o		gcm.o		havege.o	\
 		hkdf.o						\
 		hmac_drbg.o	md.o		md2.o		\
-		md4.o		md5.o		md_wrap.o	\
+		md4.o		md5.o				\
 		memory_buffer_alloc.o		nist_kw.o	\
 		oid.o		padlock.o	pem.o		\
 		pk.o		pk_wrap.o	pkcs12.o	\
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 58e1a5f..94bb7f0 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -412,11 +412,14 @@
     mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
     unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
     size_t grp_len = ( grp->nbits + 7 ) / 8;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_mpi h;
 
-    if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
+    if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) ==
+        MBEDTLS_MD_INVALID_HANDLE )
+    {
         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    }
 
     mbedtls_mpi_init( &h );
     mbedtls_hmac_drbg_init( &rng_ctx );
diff --git a/library/ecjpake.c b/library/ecjpake.c
index b276514..ea28e6d 100644
--- a/library/ecjpake.c
+++ b/library/ecjpake.c
@@ -63,7 +63,7 @@
 {
     ECJPAKE_VALIDATE( ctx != NULL );
 
-    ctx->md_info = NULL;
+    ctx->md_info = MBEDTLS_MD_INVALID_HANDLE;
     mbedtls_ecp_group_init( &ctx->grp );
     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
 
@@ -86,7 +86,7 @@
     if( ctx == NULL )
         return;
 
-    ctx->md_info = NULL;
+    ctx->md_info = MBEDTLS_MD_INVALID_HANDLE;
     mbedtls_ecp_group_free( &ctx->grp );
 
     mbedtls_ecp_point_free( &ctx->Xm1 );
@@ -119,8 +119,11 @@
 
     ctx->role = role;
 
-    if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
+    if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) ==
+        MBEDTLS_MD_INVALID_HANDLE )
+    {
         return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
+    }
 
     MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
 
@@ -140,7 +143,7 @@
 {
     ECJPAKE_VALIDATE_RET( ctx != NULL );
 
-    if( ctx->md_info == NULL ||
+    if( ctx->md_info == MBEDTLS_MD_INVALID_HANDLE ||
         ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
         ctx->s.p == NULL )
     {
@@ -190,7 +193,7 @@
 /*
  * Compute hash for ZKP (7.4.2.2.2.1)
  */
-static int ecjpake_hash( const mbedtls_md_info_t *md_info,
+static int ecjpake_hash( mbedtls_md_handle_t md_info,
                          const mbedtls_ecp_group *grp,
                          const int pf,
                          const mbedtls_ecp_point *G,
@@ -240,7 +243,7 @@
 /*
  * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
  */
-static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
+static int ecjpake_zkp_read( mbedtls_md_handle_t md_info,
                              const mbedtls_ecp_group *grp,
                              const int pf,
                              const mbedtls_ecp_point *G,
@@ -312,7 +315,7 @@
 /*
  * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
  */
-static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
+static int ecjpake_zkp_write( mbedtls_md_handle_t md_info,
                               const mbedtls_ecp_group *grp,
                               const int pf,
                               const mbedtls_ecp_point *G,
@@ -373,7 +376,7 @@
  * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
  * Output: verified public key X
  */
-static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
+static int ecjpake_kkp_read( mbedtls_md_handle_t md_info,
                              const mbedtls_ecp_group *grp,
                              const int pf,
                              const mbedtls_ecp_point *G,
@@ -410,7 +413,7 @@
  * Generate an ECJPAKEKeyKP
  * Output: the serialized structure, plus private/public key pair
  */
-static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
+static int ecjpake_kkp_write( mbedtls_md_handle_t md_info,
                               const mbedtls_ecp_group *grp,
                               const int pf,
                               const mbedtls_ecp_point *G,
@@ -447,7 +450,7 @@
  * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
  * Ouputs: verified peer public keys Xa, Xb
  */
-static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
+static int ecjpake_kkpp_read( mbedtls_md_handle_t md_info,
                               const mbedtls_ecp_group *grp,
                               const int pf,
                               const mbedtls_ecp_point *G,
@@ -480,7 +483,7 @@
  * Generate a ECJPAKEKeyKPPairList
  * Outputs: the serialized structure, plus two private/public key pairs
  */
-static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
+static int ecjpake_kkpp_write( mbedtls_md_handle_t md_info,
                                const mbedtls_ecp_group *grp,
                                const int pf,
                                const mbedtls_ecp_point *G,
diff --git a/library/hkdf.c b/library/hkdf.c
index 82d8a42..d64dc4d 100644
--- a/library/hkdf.c
+++ b/library/hkdf.c
@@ -30,7 +30,7 @@
 #include "mbedtls/hkdf.h"
 #include "mbedtls/platform_util.h"
 
-int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
+int mbedtls_hkdf( mbedtls_md_handle_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 )
@@ -51,7 +51,7 @@
     return( ret );
 }
 
-int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
+int mbedtls_hkdf_extract( mbedtls_md_handle_t md,
                           const unsigned char *salt, size_t salt_len,
                           const unsigned char *ikm, size_t ikm_len,
                           unsigned char *prk )
@@ -81,7 +81,7 @@
     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,
+int mbedtls_hkdf_expand( mbedtls_md_handle_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 )
 {
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index 34f1815..b51e9b1 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -70,7 +70,8 @@
                                   const unsigned char *additional,
                                   size_t add_len )
 {
-    size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
+    size_t md_len = mbedtls_md_get_size(
+        mbedtls_md_get_handle( &ctx->md_ctx ) );
     unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
     unsigned char sep[1];
     unsigned char K[MBEDTLS_MD_MAX_SIZE];
@@ -124,7 +125,7 @@
  * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
  */
 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
-                        const mbedtls_md_info_t * md_info,
+                        mbedtls_md_handle_t md_info,
                         const unsigned char *data, size_t data_len )
 {
     int ret;
@@ -246,7 +247,7 @@
  * from the entropy source as suggested in 8.6.7.
  */
 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
-                    const mbedtls_md_info_t * md_info,
+                    mbedtls_md_handle_t md_info,
                     int (*f_entropy)(void *, unsigned char *, size_t),
                     void *p_entropy,
                     const unsigned char *custom,
@@ -329,7 +330,8 @@
 {
     int ret;
     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
-    size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
+    size_t md_len = mbedtls_md_get_size(
+        mbedtls_md_get_handle( &ctx->md_ctx ) );
     size_t left = out_len;
     unsigned char *out = output;
 
@@ -564,7 +566,7 @@
 {
     mbedtls_hmac_drbg_context ctx;
     unsigned char buf[OUTPUT_LEN];
-    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
+    mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
 
     mbedtls_hmac_drbg_init( &ctx );
 
diff --git a/library/md.c b/library/md.c
index b3525be..882942e 100644
--- a/library/md.c
+++ b/library/md.c
@@ -32,7 +32,6 @@
 #if defined(MBEDTLS_MD_C)
 
 #include "mbedtls/md.h"
-#include "mbedtls/md_internal.h"
 #include "mbedtls/platform_util.h"
 
 #if defined(MBEDTLS_PLATFORM_C)
@@ -49,6 +48,177 @@
 #include <stdio.h>
 #endif
 
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+/*
+ *
+ * Definitions of MD information structures for various digests.
+ *
+ */
+
+/*
+ * MD-2
+ */
+#if defined(MBEDTLS_MD2_C)
+static const mbedtls_md_info_t mbedtls_md2_info = {
+    MBEDTLS_MD_MD2,
+    "MD2",
+    16,
+    16,
+    mbedtls_md2_starts_wrap,
+    mbedtls_md2_update_wrap,
+    mbedtls_md2_finish_wrap,
+    mbedtls_md2_ret,
+    mbedtls_md2_ctx_alloc,
+    mbedtls_md2_ctx_free,
+    mbedtls_md2_clone_wrap,
+    mbedtls_md2_process_wrap,
+};
+#endif /* MBEDTLS_MD2_C */
+
+/*
+ * MD-4
+ */
+
+#if defined(MBEDTLS_MD4_C)
+static const mbedtls_md_info_t mbedtls_md4_info = {
+    MBEDTLS_MD_MD4,
+    "MD4",
+    16,
+    64,
+    mbedtls_md4_starts_wrap,
+    mbedtls_md4_update_wrap,
+    mbedtls_md4_finish_wrap,
+    mbedtls_md4_ret,
+    mbedtls_md4_ctx_alloc,
+    mbedtls_md4_ctx_free,
+    mbedtls_md4_clone_wrap,
+    mbedtls_md4_process_wrap,
+};
+#endif /* MBEDTLS_MD4_C */
+
+/*
+ * MD-5
+ */
+
+#if defined(MBEDTLS_MD5_C)
+static const mbedtls_md_info_t mbedtls_md5_info = {
+    MBEDTLS_MD_MD5,
+    "MD5",
+    16,
+    64,
+    mbedtls_md5_starts_wrap,
+    mbedtls_md5_update_wrap,
+    mbedtls_md5_finish_wrap,
+    mbedtls_md5_ret,
+    mbedtls_md5_ctx_alloc,
+    mbedtls_md5_ctx_free,
+    mbedtls_md5_clone_wrap,
+    mbedtls_md5_process_wrap,
+};
+#endif /* MBEDTLS_MD5_C */
+
+/*
+ * RIPEMD-160
+ */
+
+#if defined(MBEDTLS_RIPEMD160_C)
+static const mbedtls_md_info_t mbedtls_ripemd160_info = {
+    MBEDTLS_MD_RIPEMD160,
+    "RIPEMD160",
+    20,
+    64,
+    mbedtls_ripemd160_starts_wrap,
+    mbedtls_ripemd160_update_wrap,
+    mbedtls_ripemd160_finish_wrap,
+    mbedtls_ripemd160_ret,
+    mbedtls_ripemd160_ctx_alloc,
+    mbedtls_ripemd160_ctx_free,
+    mbedtls_ripemd160_clone_wrap,
+    mbedtls_ripemd160_process_wrap,
+};
+#endif /* MBEDTLS_RIPEMD160_C */
+
+/*
+ * SHA-1
+ */
+
+#if defined(MBEDTLS_SHA1_C)
+static const mbedtls_md_info_t mbedtls_sha1_info = {
+    MBEDTLS_MD_SHA1,
+    "SHA1",
+    20,
+    64,
+    mbedtls_sha1_starts_wrap,
+    mbedtls_sha1_update_wrap,
+    mbedtls_sha1_finish_wrap,
+    mbedtls_sha1_ret,
+    mbedtls_sha1_ctx_alloc,
+    mbedtls_sha1_ctx_free,
+    mbedtls_sha1_clone_wrap,
+    mbedtls_sha1_process_wrap,
+};
+#endif /* MBEDTLS_SHA1_C */
+
+/*
+ * SHA-224 and SHA-256
+ */
+
+#if defined(MBEDTLS_SHA256_C)
+#if !defined(MBEDTLS_SHA256_NO_SHA224)
+static const mbedtls_md_info_t mbedtls_sha224_info = {
+    MBEDTLS_MD_SHA224,
+    "SHA224",
+    28,
+    64,
+    mbedtls_sha224_starts_wrap,
+    mbedtls_sha224_update_wrap,
+    mbedtls_sha224_finish_wrap,
+    mbedtls_sha224_wrap,
+    mbedtls_sha224_ctx_alloc,
+    mbedtls_sha224_ctx_free,
+    mbedtls_sha224_clone_wrap,
+    mbedtls_sha224_process_wrap,
+};
+#endif /* !MBEDTLS_SHA256_NO_SHA224 */
+static const mbedtls_md_info_t mbedtls_sha256_info =
+    MBEDTLS_MD_INFO( MBEDTLS_MD_INFO_SHA256 );
+#endif /* MBEDTLS_SHA256_C */
+
+/*
+ * SHA-384 and SHA-512
+ */
+
+#if defined(MBEDTLS_SHA512_C)
+static const mbedtls_md_info_t mbedtls_sha384_info = {
+    MBEDTLS_MD_SHA384,
+    "SHA384",
+    48,
+    128,
+    mbedtls_sha384_starts_wrap,
+    mbedtls_sha384_update_wrap,
+    mbedtls_sha384_finish_wrap,
+    mbedtls_sha384_wrap,
+    mbedtls_sha384_ctx_alloc,
+    mbedtls_sha384_ctx_free,
+    mbedtls_sha384_clone_wrap,
+    mbedtls_sha384_process_wrap,
+};
+static const mbedtls_md_info_t mbedtls_sha512_info = {
+    MBEDTLS_MD_SHA512,
+    "SHA512",
+    64,
+    128,
+    mbedtls_sha512_starts_wrap,
+    mbedtls_sha384_update_wrap,
+    mbedtls_sha384_finish_wrap,
+    mbedtls_sha512_wrap,
+    mbedtls_sha384_ctx_alloc,
+    mbedtls_sha384_ctx_free,
+    mbedtls_sha384_clone_wrap,
+    mbedtls_sha384_process_wrap,
+};
+#endif /* MBEDTLS_SHA512_C */
+
 /*
  * Reminder: update profiles in x509_crt.c when adding a new hash!
  */
@@ -94,7 +264,7 @@
     return( supported_digests );
 }
 
-const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name )
+mbedtls_md_handle_t mbedtls_md_info_from_string( const char *md_name )
 {
     if( NULL == md_name )
         return( NULL );
@@ -137,7 +307,7 @@
     return( NULL );
 }
 
-const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type )
+mbedtls_md_handle_t mbedtls_md_info_from_type( mbedtls_md_type_t md_type )
 {
     switch( md_type )
     {
@@ -180,25 +350,69 @@
     }
 }
 
+#else /* MBEDTLS_MD_SINGLE_HASH */
+
+const int *mbedtls_md_list( void )
+{
+    static int single_hash[2] =
+        { MBEDTLS_MD_INFO_TYPE( MBEDTLS_MD_SINGLE_HASH ),
+          MBEDTLS_MD_INVALID_HANDLE };
+
+    return( single_hash );
+}
+
+mbedtls_md_handle_t mbedtls_md_info_from_string( const char *md_name )
+{
+    static const char * const hash_name =
+        MBEDTLS_MD_INFO_NAME( MBEDTLS_MD_SINGLE_HASH );
+
+    if( md_name != NULL && strcmp( hash_name, md_name ) == 0 )
+        return( MBEDTLS_MD_UNIQUE_VALID_HANDLE );
+
+    return( MBEDTLS_MD_INVALID_HANDLE );
+}
+
+mbedtls_md_handle_t mbedtls_md_info_from_type( mbedtls_md_type_t md_type )
+{
+    static const mbedtls_md_type_t hash_type =
+        MBEDTLS_MD_INFO_TYPE( MBEDTLS_MD_SINGLE_HASH );
+
+    if( hash_type == md_type )
+        return( MBEDTLS_MD_UNIQUE_VALID_HANDLE );
+
+    return( MBEDTLS_MD_INVALID_HANDLE );
+}
+
+#endif /* MBEDTLS_MD_SINGLE_HASH */
+
 void mbedtls_md_init( mbedtls_md_context_t *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_md_context_t ) );
+
+#if defined(MBEDTLS_MD_SINGLE_HASH)
+    mbedtls_md_info_init( mbedtls_md_get_handle( ctx ),
+                          ctx->md_ctx );
+#endif
 }
 
 void mbedtls_md_free( mbedtls_md_context_t *ctx )
 {
-    if( ctx == NULL || ctx->md_info == NULL )
+    if( ctx == NULL || mbedtls_md_get_handle( ctx ) == MBEDTLS_MD_INVALID_HANDLE )
         return;
 
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
     if( ctx->md_ctx != NULL )
-        ctx->md_info->ctx_free_func( ctx->md_ctx );
+    {
+        mbedtls_md_info_ctx_free( mbedtls_md_get_handle( ctx ), ctx->md_ctx );
+    }
 
     if( ctx->hmac_ctx != NULL )
     {
         mbedtls_platform_zeroize( ctx->hmac_ctx,
-                                  2 * ctx->md_info->block_size );
+            2 * mbedtls_md_info_block_size( mbedtls_md_get_handle( ctx ) ) );
         mbedtls_free( ctx->hmac_ctx );
     }
+#endif /* MBEDTLS_MD_SINGLE_HASH */
 
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) );
 }
@@ -206,83 +420,57 @@
 int mbedtls_md_clone( mbedtls_md_context_t *dst,
                       const mbedtls_md_context_t *src )
 {
-    if( dst == NULL || dst->md_info == NULL ||
-        src == NULL || src->md_info == NULL ||
-        dst->md_info != src->md_info )
+    if( dst == NULL || mbedtls_md_get_handle( dst ) == MBEDTLS_MD_INVALID_HANDLE ||
+        src == NULL || mbedtls_md_get_handle( src ) == MBEDTLS_MD_INVALID_HANDLE ||
+        mbedtls_md_get_handle( dst ) != mbedtls_md_get_handle( src ) )
     {
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
     }
 
-    dst->md_info->clone_func( dst->md_ctx, src->md_ctx );
-
+    mbedtls_md_info_clone( mbedtls_md_get_handle( dst ),
+                           dst->md_ctx, src->md_ctx );
     return( 0 );
 }
 
 #if ! defined(MBEDTLS_DEPRECATED_REMOVED)
-int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info )
+int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, mbedtls_md_handle_t md_info )
 {
     return mbedtls_md_setup( ctx, md_info, 1 );
 }
 #endif
 
-int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac )
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+int mbedtls_md_setup( mbedtls_md_context_t *ctx, mbedtls_md_handle_t md_info, int hmac )
 {
-    if( md_info == NULL || ctx == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
-
-    if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
-        return( MBEDTLS_ERR_MD_ALLOC_FAILED );
-
-    if( hmac != 0 )
-    {
-        ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size );
-        if( ctx->hmac_ctx == NULL )
-        {
-            md_info->ctx_free_func( ctx->md_ctx );
-            return( MBEDTLS_ERR_MD_ALLOC_FAILED );
-        }
-    }
-
-    ctx->md_info = md_info;
-
-    return( 0 );
+    return( mbedtls_md_setup_internal( ctx, md_info, hmac ) );
 }
 
 int mbedtls_md_starts( mbedtls_md_context_t *ctx )
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
-
-    return( ctx->md_info->starts_func( ctx->md_ctx ) );
+    return( mbedtls_md_starts_internal( ctx ) );
 }
 
-int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
+int mbedtls_md_update( mbedtls_md_context_t *ctx,
+                       const unsigned char *input,
+                       size_t ilen )
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
-
-    return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
+    return( mbedtls_md_update_internal( ctx, input, ilen ) );
 }
 
 int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output )
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
-
-    return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
+    return( mbedtls_md_finish_internal( ctx, output ) );
 }
 
-int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
+int mbedtls_md( mbedtls_md_handle_t md_info, const unsigned char *input, size_t ilen,
             unsigned char *output )
 {
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
-
-    return( md_info->digest_func( input, ilen, output ) );
+    return( mbedtls_md_internal( md_info, input, ilen, output ) );
 }
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
 
 #if defined(MBEDTLS_FS_IO)
-int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output )
+int mbedtls_md_file( mbedtls_md_handle_t md_info, const char *path, unsigned char *output )
 {
     int ret;
     FILE *f;
@@ -290,7 +478,7 @@
     mbedtls_md_context_t ctx;
     unsigned char buf[1024];
 
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
     if( ( f = fopen( path, "rb" ) ) == NULL )
@@ -301,17 +489,27 @@
     if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
         goto cleanup;
 
-    if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 )
+    ret = mbedtls_md_info_starts( md_info, ctx.md_ctx );
+    if( ret != 0 )
         goto cleanup;
 
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
-        if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 )
+    {
+        ret = mbedtls_md_info_update( md_info, ctx.md_ctx,
+                                      buf, n );
+        if( ret != 0 )
             goto cleanup;
+    }
 
     if( ferror( f ) != 0 )
+    {
         ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;
+    }
     else
-        ret = md_info->finish_func( ctx.md_ctx, output );
+    {
+        ret = mbedtls_md_info_finish( md_info, ctx.md_ctx,
+                                      output );
+    }
 
 cleanup:
     mbedtls_platform_zeroize( buf, sizeof( buf ) );
@@ -329,27 +527,44 @@
     unsigned char *ipad, *opad;
     size_t i;
 
-    if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
+    mbedtls_md_handle_t md_info;
+
+    if( ctx == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    if( keylen > (size_t) ctx->md_info->block_size )
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+    if( ctx->hmac_ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
+
+    md_info = mbedtls_md_get_handle( ctx );
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    if( keylen > (size_t) mbedtls_md_info_block_size( md_info ) )
     {
-        if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
-            goto cleanup;
-        if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 )
-            goto cleanup;
-        if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 )
+        if( ( ret = mbedtls_md_info_starts( md_info, ctx->md_ctx ) ) != 0 )
             goto cleanup;
 
-        keylen = ctx->md_info->size;
+        if( ( ret = mbedtls_md_info_update( md_info, ctx->md_ctx,
+                                            key, keylen ) ) != 0 )
+        {
+            goto cleanup;
+        }
+
+        if( ( ret = mbedtls_md_info_finish( md_info, ctx->md_ctx, sum ) ) != 0 )
+            goto cleanup;
+
+        keylen = mbedtls_md_info_size( md_info );
         key = sum;
     }
 
     ipad = (unsigned char *) ctx->hmac_ctx;
-    opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
+    opad = (unsigned char *) ctx->hmac_ctx +
+        mbedtls_md_info_block_size( md_info );
 
-    memset( ipad, 0x36, ctx->md_info->block_size );
-    memset( opad, 0x5C, ctx->md_info->block_size );
+    memset( ipad, 0x36, mbedtls_md_info_block_size( md_info ) );
+    memset( opad, 0x5C, mbedtls_md_info_block_size( md_info ) );
 
     for( i = 0; i < keylen; i++ )
     {
@@ -357,11 +572,14 @@
         opad[i] = (unsigned char)( opad[i] ^ key[i] );
     }
 
-    if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+    if( ( ret = mbedtls_md_info_starts( md_info, ctx->md_ctx ) ) != 0 )
         goto cleanup;
-    if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad,
-                                           ctx->md_info->block_size ) ) != 0 )
+
+    if( ( ret = mbedtls_md_info_update( md_info, ctx->md_ctx, ipad,
+           mbedtls_md_info_block_size( md_info ) ) ) != 0 )
+    {
         goto cleanup;
+    }
 
 cleanup:
     mbedtls_platform_zeroize( sum, sizeof( sum ) );
@@ -369,12 +587,26 @@
     return( ret );
 }
 
-int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
+int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx,
+                            const unsigned char *input, size_t ilen )
 {
-    if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
+    mbedtls_md_handle_t md_info;
+
+    if( ctx == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+    if( ctx->hmac_ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
+
+    md_info = mbedtls_md_get_handle( ctx );
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    return( mbedtls_md_info_update( md_info,
+                                    ctx->md_ctx, input,
+                                    ilen ) );
 }
 
 int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
@@ -383,22 +615,45 @@
     unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
     unsigned char *opad;
 
-    if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
+    mbedtls_md_handle_t md_info;
+
+    if( ctx == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+    if( ctx->hmac_ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
 
-    if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 )
+    md_info = mbedtls_md_get_handle( ctx );
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+    opad = (unsigned char *) ctx->hmac_ctx +
+        mbedtls_md_info_block_size( md_info );
+
+    if( ( ret = mbedtls_md_info_finish( md_info, ctx->md_ctx, tmp ) ) != 0 )
         return( ret );
-    if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+
+    if( ( ret = mbedtls_md_info_starts( md_info, ctx->md_ctx ) ) != 0 )
         return( ret );
-    if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad,
-                                           ctx->md_info->block_size ) ) != 0 )
+
+    if( ( ret = mbedtls_md_info_update( md_info, ctx->md_ctx, opad,
+                       mbedtls_md_info_block_size( md_info ) ) ) != 0 )
+    {
         return( ret );
-    if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp,
-                                           ctx->md_info->size ) ) != 0 )
+    }
+
+    if( ( ret = mbedtls_md_info_update( md_info, ctx->md_ctx, tmp,
+                        mbedtls_md_info_size( md_info ) ) ) != 0 )
+    {
         return( ret );
-    return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
+    }
+
+    if( ( ret = mbedtls_md_info_finish( md_info, ctx->md_ctx, output ) ) != 0 )
+        return( ret );
+
+    return( 0 );
 }
 
 int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx )
@@ -406,18 +661,33 @@
     int ret;
     unsigned char *ipad;
 
-    if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
+    mbedtls_md_handle_t md_info;
+
+    if( ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
+    if( ctx->hmac_ctx == NULL )
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
+
+    md_info = mbedtls_md_get_handle( ctx );
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
     ipad = (unsigned char *) ctx->hmac_ctx;
 
-    if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+    ret = mbedtls_md_info_starts( md_info, ctx->md_ctx );
+    if( ret != 0 )
         return( ret );
-    return( ctx->md_info->update_func( ctx->md_ctx, ipad,
-                                       ctx->md_info->block_size ) );
+
+    ret = mbedtls_md_info_update( md_info,
+                                  ctx->md_ctx, ipad,
+                                  mbedtls_md_info_block_size( md_info ) );
+    return( ret );
 }
 
-int mbedtls_md_hmac( const mbedtls_md_info_t *md_info,
+int mbedtls_md_hmac( mbedtls_md_handle_t md_info,
                      const unsigned char *key, size_t keylen,
                      const unsigned char *input, size_t ilen,
                      unsigned char *output )
@@ -425,7 +695,7 @@
     mbedtls_md_context_t ctx;
     int ret;
 
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
     mbedtls_md_init( &ctx );
@@ -446,36 +716,35 @@
     return( ret );
 }
 
+#if !defined(MBEDTLS_MD_SINGLE_HASH)
 int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data )
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
-
-    return( ctx->md_info->process_func( ctx->md_ctx, data ) );
+    return( mbedtls_md_process_internal( ctx, data ) );
 }
+#endif /* !MBEDTLS_MD_SINGLE_HASH */
 
-unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info )
+unsigned char mbedtls_md_get_size( mbedtls_md_handle_t md_info )
 {
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( 0 );
 
-    return md_info->size;
+    return mbedtls_md_info_size( md_info );
 }
 
-mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info )
+mbedtls_md_type_t mbedtls_md_get_type( mbedtls_md_handle_t md_info )
 {
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_MD_NONE );
 
-    return md_info->type;
+    return mbedtls_md_info_type( md_info );
 }
 
-const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info )
+const char *mbedtls_md_get_name( mbedtls_md_handle_t md_info )
 {
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( NULL );
 
-    return md_info->name;
+    return mbedtls_md_info_name( md_info );
 }
 
 #endif /* MBEDTLS_MD_C */
diff --git a/library/md_wrap.c b/library/md_wrap.c
deleted file mode 100644
index 0f8132f..0000000
--- a/library/md_wrap.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/**
- * \file md_wrap.c
- *
- * \brief Generic message digest wrapper for mbed TLS
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- *  Copyright (C) 2006-2015, 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_MD_C)
-
-#include "mbedtls/md_internal.h"
-
-#if defined(MBEDTLS_MD2_C)
-#include "mbedtls/md2.h"
-#endif
-
-#if defined(MBEDTLS_MD4_C)
-#include "mbedtls/md4.h"
-#endif
-
-#if defined(MBEDTLS_MD5_C)
-#include "mbedtls/md5.h"
-#endif
-
-#if defined(MBEDTLS_RIPEMD160_C)
-#include "mbedtls/ripemd160.h"
-#endif
-
-#if defined(MBEDTLS_SHA1_C)
-#include "mbedtls/sha1.h"
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-#include "mbedtls/sha256.h"
-#endif
-
-#if defined(MBEDTLS_SHA512_C)
-#include "mbedtls/sha512.h"
-#endif
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
-
-#if defined(MBEDTLS_MD2_C)
-
-static int md2_starts_wrap( void *ctx )
-{
-    return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) );
-}
-
-static int md2_update_wrap( void *ctx, const unsigned char *input,
-                             size_t ilen )
-{
-    return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) );
-}
-
-static int md2_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) );
-}
-
-static void *md2_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) );
-
-    if( ctx != NULL )
-        mbedtls_md2_init( (mbedtls_md2_context *) ctx );
-
-    return( ctx );
-}
-
-static void md2_ctx_free( void *ctx )
-{
-    mbedtls_md2_free( (mbedtls_md2_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void md2_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_md2_clone( (mbedtls_md2_context *) dst,
-                 (const mbedtls_md2_context *) src );
-}
-
-static int md2_process_wrap( void *ctx, const unsigned char *data )
-{
-    ((void) data);
-
-    return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) );
-}
-
-const mbedtls_md_info_t mbedtls_md2_info = {
-    MBEDTLS_MD_MD2,
-    "MD2",
-    16,
-    16,
-    md2_starts_wrap,
-    md2_update_wrap,
-    md2_finish_wrap,
-    mbedtls_md2_ret,
-    md2_ctx_alloc,
-    md2_ctx_free,
-    md2_clone_wrap,
-    md2_process_wrap,
-};
-
-#endif /* MBEDTLS_MD2_C */
-
-#if defined(MBEDTLS_MD4_C)
-
-static int md4_starts_wrap( void *ctx )
-{
-    return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) );
-}
-
-static int md4_update_wrap( void *ctx, const unsigned char *input,
-                             size_t ilen )
-{
-    return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) );
-}
-
-static int md4_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) );
-}
-
-static void *md4_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) );
-
-    if( ctx != NULL )
-        mbedtls_md4_init( (mbedtls_md4_context *) ctx );
-
-    return( ctx );
-}
-
-static void md4_ctx_free( void *ctx )
-{
-    mbedtls_md4_free( (mbedtls_md4_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void md4_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_md4_clone( (mbedtls_md4_context *) dst,
-                       (const mbedtls_md4_context *) src );
-}
-
-static int md4_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_md4_info = {
-    MBEDTLS_MD_MD4,
-    "MD4",
-    16,
-    64,
-    md4_starts_wrap,
-    md4_update_wrap,
-    md4_finish_wrap,
-    mbedtls_md4_ret,
-    md4_ctx_alloc,
-    md4_ctx_free,
-    md4_clone_wrap,
-    md4_process_wrap,
-};
-
-#endif /* MBEDTLS_MD4_C */
-
-#if defined(MBEDTLS_MD5_C)
-
-static int md5_starts_wrap( void *ctx )
-{
-    return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) );
-}
-
-static int md5_update_wrap( void *ctx, const unsigned char *input,
-                             size_t ilen )
-{
-    return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) );
-}
-
-static int md5_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) );
-}
-
-static void *md5_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) );
-
-    if( ctx != NULL )
-        mbedtls_md5_init( (mbedtls_md5_context *) ctx );
-
-    return( ctx );
-}
-
-static void md5_ctx_free( void *ctx )
-{
-    mbedtls_md5_free( (mbedtls_md5_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void md5_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_md5_clone( (mbedtls_md5_context *) dst,
-                       (const mbedtls_md5_context *) src );
-}
-
-static int md5_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_md5_info = {
-    MBEDTLS_MD_MD5,
-    "MD5",
-    16,
-    64,
-    md5_starts_wrap,
-    md5_update_wrap,
-    md5_finish_wrap,
-    mbedtls_md5_ret,
-    md5_ctx_alloc,
-    md5_ctx_free,
-    md5_clone_wrap,
-    md5_process_wrap,
-};
-
-#endif /* MBEDTLS_MD5_C */
-
-#if defined(MBEDTLS_RIPEMD160_C)
-
-static int ripemd160_starts_wrap( void *ctx )
-{
-    return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) );
-}
-
-static int ripemd160_update_wrap( void *ctx, const unsigned char *input,
-                                   size_t ilen )
-{
-    return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx,
-                                          input, ilen ) );
-}
-
-static int ripemd160_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx,
-                                          output ) );
-}
-
-static void *ripemd160_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) );
-
-    if( ctx != NULL )
-        mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx );
-
-    return( ctx );
-}
-
-static void ripemd160_ctx_free( void *ctx )
-{
-    mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void ripemd160_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst,
-                       (const mbedtls_ripemd160_context *) src );
-}
-
-static int ripemd160_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_ripemd160_process(
-                                (mbedtls_ripemd160_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_ripemd160_info = {
-    MBEDTLS_MD_RIPEMD160,
-    "RIPEMD160",
-    20,
-    64,
-    ripemd160_starts_wrap,
-    ripemd160_update_wrap,
-    ripemd160_finish_wrap,
-    mbedtls_ripemd160_ret,
-    ripemd160_ctx_alloc,
-    ripemd160_ctx_free,
-    ripemd160_clone_wrap,
-    ripemd160_process_wrap,
-};
-
-#endif /* MBEDTLS_RIPEMD160_C */
-
-#if defined(MBEDTLS_SHA1_C)
-
-static int sha1_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) );
-}
-
-static int sha1_update_wrap( void *ctx, const unsigned char *input,
-                              size_t ilen )
-{
-    return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx,
-                                     input, ilen ) );
-}
-
-static int sha1_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) );
-}
-
-static void *sha1_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) );
-
-    if( ctx != NULL )
-        mbedtls_sha1_init( (mbedtls_sha1_context *) ctx );
-
-    return( ctx );
-}
-
-static void sha1_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_sha1_clone( (mbedtls_sha1_context *) dst,
-                  (const mbedtls_sha1_context *) src );
-}
-
-static void sha1_ctx_free( void *ctx )
-{
-    mbedtls_sha1_free( (mbedtls_sha1_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static int sha1_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx,
-                                           data ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha1_info = {
-    MBEDTLS_MD_SHA1,
-    "SHA1",
-    20,
-    64,
-    sha1_starts_wrap,
-    sha1_update_wrap,
-    sha1_finish_wrap,
-    mbedtls_sha1_ret,
-    sha1_ctx_alloc,
-    sha1_ctx_free,
-    sha1_clone_wrap,
-    sha1_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA1_C */
-
-/*
- * Wrappers for generic message digests
- */
-#if defined(MBEDTLS_SHA256_C)
-
-#if !defined(MBEDTLS_SHA256_NO_SHA224)
-static int sha224_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) );
-}
-#endif /* !MBEDTLS_SHA256_NO_SHA224 */
-
-static int sha224_update_wrap( void *ctx, const unsigned char *input,
-                                size_t ilen )
-{
-    return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx,
-                                       input, ilen ) );
-}
-
-static int sha224_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx,
-                                       output ) );
-}
-
-#if !defined(MBEDTLS_SHA256_NO_SHA224)
-static int sha224_wrap( const unsigned char *input, size_t ilen,
-                        unsigned char *output )
-{
-    return( mbedtls_sha256_ret( input, ilen, output, 1 ) );
-}
-#endif /* !MBEDTLS_SHA256_NO_SHA224 */
-
-static void *sha224_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) );
-
-    if( ctx != NULL )
-        mbedtls_sha256_init( (mbedtls_sha256_context *) ctx );
-
-    return( ctx );
-}
-
-static void sha224_ctx_free( void *ctx )
-{
-    mbedtls_sha256_free( (mbedtls_sha256_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void sha224_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_sha256_clone( (mbedtls_sha256_context *) dst,
-                    (const mbedtls_sha256_context *) src );
-}
-
-static int sha224_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx,
-                                             data ) );
-}
-
-#if !defined(MBEDTLS_SHA256_NO_SHA224)
-const mbedtls_md_info_t mbedtls_sha224_info = {
-    MBEDTLS_MD_SHA224,
-    "SHA224",
-    28,
-    64,
-    sha224_starts_wrap,
-    sha224_update_wrap,
-    sha224_finish_wrap,
-    sha224_wrap,
-    sha224_ctx_alloc,
-    sha224_ctx_free,
-    sha224_clone_wrap,
-    sha224_process_wrap,
-};
-#endif /* !MBEDTLS_SHA256_NO_SHA224 */
-
-static int sha256_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) );
-}
-
-static int sha256_wrap( const unsigned char *input, size_t ilen,
-                        unsigned char *output )
-{
-    return( mbedtls_sha256_ret( input, ilen, output, 0 ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha256_info = {
-    MBEDTLS_MD_SHA256,
-    "SHA256",
-    32,
-    64,
-    sha256_starts_wrap,
-    sha224_update_wrap,
-    sha224_finish_wrap,
-    sha256_wrap,
-    sha224_ctx_alloc,
-    sha224_ctx_free,
-    sha224_clone_wrap,
-    sha224_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA256_C */
-
-#if defined(MBEDTLS_SHA512_C)
-
-static int sha384_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) );
-}
-
-static int sha384_update_wrap( void *ctx, const unsigned char *input,
-                               size_t ilen )
-{
-    return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx,
-                                       input, ilen ) );
-}
-
-static int sha384_finish_wrap( void *ctx, unsigned char *output )
-{
-    return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx,
-                                       output ) );
-}
-
-static int sha384_wrap( const unsigned char *input, size_t ilen,
-                        unsigned char *output )
-{
-    return( mbedtls_sha512_ret( input, ilen, output, 1 ) );
-}
-
-static void *sha384_ctx_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) );
-
-    if( ctx != NULL )
-        mbedtls_sha512_init( (mbedtls_sha512_context *) ctx );
-
-    return( ctx );
-}
-
-static void sha384_ctx_free( void *ctx )
-{
-    mbedtls_sha512_free( (mbedtls_sha512_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void sha384_clone_wrap( void *dst, const void *src )
-{
-    mbedtls_sha512_clone( (mbedtls_sha512_context *) dst,
-                    (const mbedtls_sha512_context *) src );
-}
-
-static int sha384_process_wrap( void *ctx, const unsigned char *data )
-{
-    return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx,
-                                             data ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha384_info = {
-    MBEDTLS_MD_SHA384,
-    "SHA384",
-    48,
-    128,
-    sha384_starts_wrap,
-    sha384_update_wrap,
-    sha384_finish_wrap,
-    sha384_wrap,
-    sha384_ctx_alloc,
-    sha384_ctx_free,
-    sha384_clone_wrap,
-    sha384_process_wrap,
-};
-
-static int sha512_starts_wrap( void *ctx )
-{
-    return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) );
-}
-
-static int sha512_wrap( const unsigned char *input, size_t ilen,
-                        unsigned char *output )
-{
-    return( mbedtls_sha512_ret( input, ilen, output, 0 ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha512_info = {
-    MBEDTLS_MD_SHA512,
-    "SHA512",
-    64,
-    128,
-    sha512_starts_wrap,
-    sha384_update_wrap,
-    sha384_finish_wrap,
-    sha512_wrap,
-    sha384_ctx_alloc,
-    sha384_ctx_free,
-    sha384_clone_wrap,
-    sha384_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA512_C */
-
-#endif /* MBEDTLS_MD_C */
diff --git a/library/pk.c b/library/pk.c
index 161a135..93c5764 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -205,13 +205,16 @@
  */
 static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len )
 {
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
 
     if( *hash_len != 0 )
         return( 0 );
 
-    if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
+    if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) ==
+        MBEDTLS_MD_INVALID_HANDLE )
+    {
         return( -1 );
+    }
 
     *hash_len = mbedtls_md_get_size( md_info );
     return( 0 );
diff --git a/library/pkcs11.c b/library/pkcs11.c
index 0ea6425..9ef5353 100644
--- a/library/pkcs11.c
+++ b/library/pkcs11.c
@@ -183,8 +183,8 @@
 
     if( md_alg != MBEDTLS_MD_NONE )
     {
-        const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
-        if( md_info == NULL )
+        mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( md_alg );
+        if( md_info == MBEDTLS_MD_INVALID_HANDLE )
             return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
         if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
diff --git a/library/pkcs12.c b/library/pkcs12.c
index 7edf064..e16d0a9 100644
--- a/library/pkcs12.c
+++ b/library/pkcs12.c
@@ -261,7 +261,7 @@
 
     size_t hlen, use_len, v, i;
 
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_md_context_t md_ctx;
 
     // This version only allows max of 64 bytes of password or salt
@@ -269,7 +269,7 @@
         return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
 
     md_info = mbedtls_md_info_from_type( md_type );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
 
     mbedtls_md_init( &md_ctx );
diff --git a/library/pkcs5.c b/library/pkcs5.c
index 5013343..a517778 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -122,7 +122,7 @@
     mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
     unsigned char key[32], iv[32];
     size_t olen = 0;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     const mbedtls_cipher_info_t *cipher_info;
     mbedtls_md_context_t md_ctx;
     mbedtls_cipher_type_t cipher_alg;
@@ -157,7 +157,7 @@
     }
 
     md_info = mbedtls_md_info_from_type( md_type );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
     if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid,
@@ -226,7 +226,7 @@
     unsigned int i;
     unsigned char md1[MBEDTLS_MD_MAX_SIZE];
     unsigned char work[MBEDTLS_MD_MAX_SIZE];
-    unsigned char md_size = mbedtls_md_get_size( ctx->md_info );
+    unsigned char md_size = mbedtls_md_get_size( mbedtls_md_get_handle( ctx ) );
     size_t use_len;
     unsigned char *out_p = output;
     unsigned char counter[4];
@@ -356,14 +356,14 @@
 int mbedtls_pkcs5_self_test( int verbose )
 {
     mbedtls_md_context_t sha1_ctx;
-    const mbedtls_md_info_t *info_sha1;
+    mbedtls_md_handle_t info_sha1;
     int ret, i;
     unsigned char key[64];
 
     mbedtls_md_init( &sha1_ctx );
 
     info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
-    if( info_sha1 == NULL )
+    if( info_sha1 == MBEDTLS_MD_INVALID_HANDLE )
     {
         ret = 1;
         goto exit;
diff --git a/library/rsa.c b/library/rsa.c
index af1a878..3bfc73e 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -1076,7 +1076,7 @@
     memset( mask, 0, MBEDTLS_MD_MAX_SIZE );
     memset( counter, 0, 4 );
 
-    hlen = mbedtls_md_get_size( md_ctx->md_info );
+    hlen = mbedtls_md_get_size( mbedtls_md_get_handle( md_ctx ) );
 
     /* Generate and apply dbMask */
     p = dst;
@@ -1128,7 +1128,7 @@
     int ret;
     unsigned char *p = output;
     unsigned int hlen;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_md_context_t md_ctx;
 
     RSA_VALIDATE_RET( ctx != NULL );
@@ -1145,7 +1145,7 @@
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
     md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
     olen = ctx->len;
@@ -1326,7 +1326,7 @@
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
     unsigned char lhash[MBEDTLS_MD_MAX_SIZE];
     unsigned int hlen;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_md_context_t md_ctx;
 
     RSA_VALIDATE_RET( ctx != NULL );
@@ -1349,7 +1349,7 @@
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
     md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
     hlen = mbedtls_md_get_size( md_info );
@@ -1767,7 +1767,7 @@
     size_t slen, min_slen, hlen, offset = 0;
     int ret;
     size_t msb;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_md_context_t md_ctx;
     RSA_VALIDATE_RET( ctx != NULL );
     RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
@@ -1789,14 +1789,14 @@
     {
         /* Gather length of hash to sign */
         md_info = mbedtls_md_info_from_type( md_alg );
-        if( md_info == NULL )
+        if( md_info == MBEDTLS_MD_INVALID_HANDLE )
             return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
         hashlen = mbedtls_md_get_size( md_info );
     }
 
     md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
     hlen = mbedtls_md_get_size( md_info );
@@ -1910,8 +1910,8 @@
     /* Are we signing hashed or raw data? */
     if( md_alg != MBEDTLS_MD_NONE )
     {
-        const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
-        if( md_info == NULL )
+        mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( md_alg );
+        if( md_info == MBEDTLS_MD_INVALID_HANDLE )
             return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
         if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
@@ -2150,7 +2150,7 @@
     unsigned char zeros[8];
     unsigned int hlen;
     size_t observed_salt_len, msb;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_md_context_t md_ctx;
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
 
@@ -2186,14 +2186,14 @@
     {
         /* Gather length of hash to sign */
         md_info = mbedtls_md_info_from_type( md_alg );
-        if( md_info == NULL )
+        if( md_info == MBEDTLS_MD_INVALID_HANDLE )
             return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
         hashlen = mbedtls_md_get_size( md_info );
     }
 
     md_info = mbedtls_md_info_from_type( mgf1_hash_id );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
     hlen = mbedtls_md_get_size( md_info );
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index e3aabb7..0a1322a 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -739,8 +739,10 @@
     if( suite_info == MBEDTLS_SSL_CIPHERSUITE_INVALID_HANDLE )
         return( 1 );
 
-    if( mbedtls_ssl_suite_get_min_minor_ver( suite_info ) > max_minor_ver ||
-        mbedtls_ssl_suite_get_max_minor_ver( suite_info ) < min_minor_ver )
+    if( mbedtls_ssl_ver_gt( mbedtls_ssl_suite_get_min_minor_ver( suite_info ),
+                            max_minor_ver ) ||
+        mbedtls_ssl_ver_lt( mbedtls_ssl_suite_get_max_minor_ver( suite_info ),
+                            min_minor_ver ) )
     {
         return( 1 );
     }
@@ -1520,10 +1522,12 @@
      * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1)
      * even is lower than our min version.
      */
-    if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 ||
-        minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ||
-        major_ver > mbedtls_ssl_conf_get_max_major_ver( ssl->conf )  ||
-        minor_ver > mbedtls_ssl_conf_get_max_minor_ver( ssl->conf )  )
+    if( mbedtls_ssl_ver_lt( major_ver, MBEDTLS_SSL_MAJOR_VERSION_3 ) ||
+        mbedtls_ssl_ver_lt( minor_ver, MBEDTLS_SSL_MINOR_VERSION_2 ) ||
+        mbedtls_ssl_ver_gt( major_ver,
+                            mbedtls_ssl_conf_get_max_major_ver( ssl->conf ) ) ||
+        mbedtls_ssl_ver_gt( minor_ver,
+                            mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) );
 
@@ -1678,10 +1682,14 @@
                                   ssl->conf->transport,
                                   buf + 0 );
 
-        if( major_ver < mbedtls_ssl_conf_get_min_major_ver( ssl->conf ) ||
-            minor_ver < mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ) ||
-            major_ver > mbedtls_ssl_conf_get_max_major_ver( ssl->conf ) ||
-            minor_ver > mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) )
+        if( mbedtls_ssl_ver_lt( major_ver,
+                                mbedtls_ssl_conf_get_min_major_ver( ssl->conf ) ) ||
+            mbedtls_ssl_ver_lt( minor_ver,
+                                mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ) ) ||
+            mbedtls_ssl_ver_gt( major_ver,
+                                mbedtls_ssl_conf_get_max_major_ver( ssl->conf ) ) ||
+            mbedtls_ssl_ver_gt( minor_ver,
+                                mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - "
                          " min: [%d:%d], server: [%d:%d], max: [%d:%d]",
@@ -2909,7 +2917,8 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_1)
-        if( mbedtls_ssl_get_minor_ver( ssl ) < MBEDTLS_SSL_MINOR_VERSION_3 )
+        if( mbedtls_ssl_ver_lt( mbedtls_ssl_get_minor_ver( ssl ),
+                                MBEDTLS_SSL_MINOR_VERSION_3 ) )
         {
             pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
 
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 3afc565..69af317 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -884,7 +884,8 @@
          * present them a SHA-higher cert rather than failing if it's the only
          * one we got that satisfies the other conditions.
          */
-        if( mbedtls_ssl_get_minor_ver( ssl ) < MBEDTLS_SSL_MINOR_VERSION_3 )
+        if( mbedtls_ssl_ver_lt( mbedtls_ssl_get_minor_ver( ssl ),
+                                MBEDTLS_SSL_MINOR_VERSION_3 ) )
         {
             mbedtls_md_type_t sig_md;
             {
@@ -951,10 +952,12 @@
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s",
                                 mbedtls_ssl_suite_get_name( suite_info ) ) );
 
-    if( mbedtls_ssl_suite_get_min_minor_ver( suite_info )
-          > mbedtls_ssl_get_minor_ver( ssl ) ||
-        mbedtls_ssl_suite_get_max_minor_ver( suite_info )
-          < mbedtls_ssl_get_minor_ver( ssl ) )
+    if( mbedtls_ssl_ver_gt(
+            mbedtls_ssl_suite_get_min_minor_ver( suite_info ),
+            mbedtls_ssl_get_minor_ver( ssl ) ) ||
+        mbedtls_ssl_ver_lt(
+            mbedtls_ssl_suite_get_max_minor_ver( suite_info ),
+            mbedtls_ssl_get_minor_ver( ssl ) ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) );
         return( 0 );
@@ -1126,7 +1129,8 @@
         ? buf[4]  : mbedtls_ssl_conf_get_max_minor_ver( ssl->conf );
 #endif
 
-    if( mbedtls_ssl_get_minor_ver( ssl ) < mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ) )
+    if( mbedtls_ssl_ver_lt( mbedtls_ssl_get_minor_ver( ssl ),
+                            mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ) ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
                             " [%d:%d] < [%d:%d]",
@@ -1252,8 +1256,9 @@
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) );
 
-            if( mbedtls_ssl_get_minor_ver( ssl ) <
-                mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) )
+            if( mbedtls_ssl_ver_lt(
+                    mbedtls_ssl_get_minor_ver( ssl ),
+                    mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) ) )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) );
 
@@ -1669,8 +1674,10 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED ||
           MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 
-        if( major_ver < mbedtls_ssl_conf_get_min_major_ver( ssl->conf ) ||
-            minor_ver < mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ) )
+        if( mbedtls_ssl_ver_lt( major_ver,
+                                mbedtls_ssl_conf_get_min_major_ver( ssl->conf ) ) ||
+            mbedtls_ssl_ver_lt( minor_ver,
+                                mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ) ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
                             " [%d:%d] < [%d:%d]",
@@ -1682,13 +1689,19 @@
             return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
         }
 
-        if( major_ver > mbedtls_ssl_conf_get_max_major_ver( ssl->conf ) )
+        if( mbedtls_ssl_ver_gt(
+                major_ver,
+                mbedtls_ssl_conf_get_max_major_ver( ssl->conf ) ) )
         {
             major_ver = mbedtls_ssl_conf_get_max_major_ver( ssl->conf );
             minor_ver = mbedtls_ssl_conf_get_max_minor_ver( ssl->conf );
         }
-        else if( minor_ver > mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) )
+        else if( mbedtls_ssl_ver_gt(
+                     minor_ver,
+                     mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) ) )
+        {
             minor_ver = mbedtls_ssl_conf_get_max_minor_ver( ssl->conf );
+        }
 
 #if !defined(MBEDTLS_SSL_CONF_FIXED_MAJOR_VER)
         ssl->major_ver = major_ver;
@@ -2077,8 +2090,9 @@
         {
             MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) );
 
-            if( mbedtls_ssl_get_minor_ver( ssl ) <
-                mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) )
+            if( mbedtls_ssl_ver_lt(
+                    mbedtls_ssl_get_minor_ver( ssl ),
+                    mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) ) )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) );
 
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index cf6ef12..850bcb1 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -660,7 +660,7 @@
     const unsigned char *S1, *S2;
     unsigned char tmp[128];
     unsigned char h_i[20];
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_md_context_t md_ctx;
     int ret;
 
@@ -681,8 +681,11 @@
     /*
      * First compute P_md5(secret,label+random)[0..dlen]
      */
-    if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL )
+    if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) ==
+        MBEDTLS_MD_INVALID_HANDLE )
+    {
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
 
     if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
         return( ret );
@@ -712,8 +715,11 @@
     /*
      * XOR out with P_sha1(secret,label+random)[0..dlen]
      */
-    if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL )
+    if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) ==
+        MBEDTLS_MD_INVALID_HANDLE )
+    {
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
 
     if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
         return( ret );
@@ -763,14 +769,17 @@
     size_t i, j, k, md_len;
     unsigned char tmp[128];
     unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_md_context_t md_ctx;
     int ret;
 
     mbedtls_md_init( &md_ctx );
 
-    if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL )
+    if( ( md_info = mbedtls_md_info_from_type( md_type ) ) ==
+        MBEDTLS_MD_INVALID_HANDLE )
+    {
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
 
     md_len = mbedtls_md_get_size( md_info );
 
@@ -861,7 +870,7 @@
     else
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    if( minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
+    if( mbedtls_ssl_ver_lt( minor_ver, MBEDTLS_SSL_MINOR_VERSION_3 ) )
         return( tls1_prf( secret, slen, label, random, rlen, dstbuf, dlen ) );
     else
 #endif
@@ -1160,7 +1169,7 @@
     else
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    if( minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
+    if( mbedtls_ssl_ver_lt( minor_ver, MBEDTLS_SSL_MINOR_VERSION_3 ) )
         ssl_calc_finished_tls( ssl, buf, from );
     else
 #endif
@@ -1244,7 +1253,7 @@
     unsigned keylen;
     mbedtls_ssl_ciphersuite_handle_t ciphersuite_info;
     const mbedtls_cipher_info_t *cipher_info;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
 
 #if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \
     !defined(MBEDTLS_SSL_EXPORT_KEYS) && \
@@ -1293,7 +1302,7 @@
 
     md_info = mbedtls_md_info_from_type(
         mbedtls_ssl_suite_get_mac( ciphersuite_info ) );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found",
                        mbedtls_ssl_suite_get_mac( ciphersuite_info ) ) );
@@ -1484,7 +1493,7 @@
 #endif /* MBEDTLS_SSL_PROTO_SSL3 */
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
+    if( mbedtls_ssl_ver_geq( minor_ver, MBEDTLS_SSL_MINOR_VERSION_1 ) )
     {
         /* For HMAC-based ciphersuites, initialize the HMAC transforms.
            For AEAD-based ciphersuites, there is nothing to do here. */
@@ -1759,7 +1768,7 @@
     else
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    if( minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
+    if( mbedtls_ssl_ver_lt( minor_ver, MBEDTLS_SSL_MINOR_VERSION_3 ) )
         ssl_calc_verify_tls( ssl, dst, hlen );
     else
 #endif
@@ -2526,8 +2535,9 @@
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
         defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( mbedtls_ssl_transform_get_minor_ver( transform ) >=
-            MBEDTLS_SSL_MINOR_VERSION_1 )
+        if( mbedtls_ssl_ver_geq(
+                mbedtls_ssl_transform_get_minor_ver( transform ),
+                MBEDTLS_SSL_MINOR_VERSION_1 ) )
         {
             unsigned char mac[MBEDTLS_SSL_MAC_ADD];
 
@@ -2706,8 +2716,9 @@
          * Prepend per-record IV for block cipher in TLS v1.1 and up as per
          * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
          */
-        if( mbedtls_ssl_transform_get_minor_ver( transform ) >=
-            MBEDTLS_SSL_MINOR_VERSION_2 )
+        if( mbedtls_ssl_ver_geq(
+                mbedtls_ssl_transform_get_minor_ver( transform ),
+                MBEDTLS_SSL_MINOR_VERSION_2 ) )
         {
             if( f_rng == NULL )
             {
@@ -2756,8 +2767,9 @@
         }
 
 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
-        if( mbedtls_ssl_transform_get_minor_ver( transform ) <
-            MBEDTLS_SSL_MINOR_VERSION_2 )
+        if( mbedtls_ssl_ver_lt(
+                mbedtls_ssl_transform_get_minor_ver( transform ),
+                MBEDTLS_SSL_MINOR_VERSION_2 ) )
         {
             /*
              * Save IV in SSL3 and TLS1
@@ -3014,8 +3026,9 @@
          * Check immediate ciphertext sanity
          */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( mbedtls_ssl_transform_get_minor_ver( transform ) >=
-            MBEDTLS_SSL_MINOR_VERSION_2 )
+        if( mbedtls_ssl_ver_geq(
+                mbedtls_ssl_transform_get_minor_ver( transform ),
+                MBEDTLS_SSL_MINOR_VERSION_2 ) )
         {
             /* The ciphertext is prefixed with the CBC IV. */
             minlen += transform->ivlen;
@@ -3120,8 +3133,9 @@
         /*
          * Initialize for prepended IV for block cipher in TLS v1.1 and up
          */
-        if( mbedtls_ssl_transform_get_minor_ver( transform ) >=
-            MBEDTLS_SSL_MINOR_VERSION_2 )
+        if( mbedtls_ssl_ver_geq(
+                mbedtls_ssl_transform_get_minor_ver( transform ),
+                MBEDTLS_SSL_MINOR_VERSION_2 ) )
         {
             /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */
             memcpy( transform->iv_dec, data, transform->ivlen );
@@ -3150,8 +3164,9 @@
         }
 
 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
-        if( mbedtls_ssl_transform_get_minor_ver( transform ) <
-            MBEDTLS_SSL_MINOR_VERSION_2 )
+        if( mbedtls_ssl_ver_lt(
+                mbedtls_ssl_transform_get_minor_ver( transform ),
+                MBEDTLS_SSL_MINOR_VERSION_2 ) )
         {
             /*
              * Save IV in SSL3 and TLS1, where CBC decryption of consecutive
@@ -3214,8 +3229,9 @@
 #endif /* MBEDTLS_SSL_PROTO_SSL3 */
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( mbedtls_ssl_transform_get_minor_ver( transform ) >
-            MBEDTLS_SSL_MINOR_VERSION_0 )
+        if( mbedtls_ssl_ver_gt(
+                mbedtls_ssl_transform_get_minor_ver( transform ),
+                MBEDTLS_SSL_MINOR_VERSION_0 ) )
         {
             /* The padding check involves a series of up to 256
              * consecutive memory reads at the end of the record
@@ -3313,8 +3329,9 @@
 #endif /* MBEDTLS_SSL_PROTO_SSL3 */
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
         defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( mbedtls_ssl_transform_get_minor_ver( transform ) >
-            MBEDTLS_SSL_MINOR_VERSION_0 )
+        if( mbedtls_ssl_ver_gt(
+                mbedtls_ssl_transform_get_minor_ver( transform ),
+                MBEDTLS_SSL_MINOR_VERSION_0 ) )
         {
             /*
              * Process MAC and always update for padlen afterwards to make
@@ -3361,7 +3378,8 @@
 
             memset( tmp, 0, sizeof( tmp ) );
 
-            switch( mbedtls_md_get_type( transform->md_ctx_dec.md_info ) )
+            switch( mbedtls_md_get_type(
+                        mbedtls_md_get_handle( &transform->md_ctx_dec ) ) )
             {
 #if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \
     defined(MBEDTLS_SHA256_C)
@@ -5320,7 +5338,8 @@
         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
     }
 
-    if( minor_ver > mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) )
+    if( mbedtls_ssl_ver_gt( minor_ver,
+                            mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -6865,13 +6884,16 @@
         ssl->session->peer_cert_digest;
     mbedtls_md_type_t const peer_cert_digest_type =
         ssl->session->peer_cert_digest_type;
-    mbedtls_md_info_t const * const digest_info =
+    mbedtls_md_handle_t digest_info =
         mbedtls_md_info_from_type( peer_cert_digest_type );
     unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN];
     size_t digest_len;
 
-    if( peer_cert_digest == NULL || digest_info == NULL )
+    if( peer_cert_digest == NULL ||
+        digest_info == MBEDTLS_MD_INVALID_HANDLE )
+    {
         return( -1 );
+    }
 
     digest_len = mbedtls_md_get_size( digest_info );
     if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN )
@@ -7155,7 +7177,10 @@
         ssl->hostname,
 #endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
         &ssl->session_negotiate->verify_result,
-        ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+        ssl->conf->f_vrfy, ssl->conf->p_vrfy,
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+        rs_ctx );
 
     if( verify_ret != 0 )
     {
@@ -8136,7 +8161,9 @@
 
     /* Adjust out_msg to make space for explicit IV, if used. */
     if( transform != NULL &&
-        mbedtls_ssl_get_minor_ver( ssl ) >= MBEDTLS_SSL_MINOR_VERSION_2 )
+        mbedtls_ssl_ver_geq(
+            mbedtls_ssl_get_minor_ver( ssl ),
+            MBEDTLS_SSL_MINOR_VERSION_2 ) )
     {
         ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen;
     }
@@ -8497,7 +8524,8 @@
 #endif /* MBEDTLS_SSL_CONF_AUTHMODE */
 }
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+    !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
 void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf,
                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                      void *p_vrfy )
@@ -8505,7 +8533,7 @@
     conf->f_vrfy      = f_vrfy;
     conf->p_vrfy      = p_vrfy;
 }
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 
 #if !defined(MBEDTLS_SSL_CONF_RNG)
 void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf,
@@ -8625,10 +8653,10 @@
 void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf,
                                    const int *ciphersuites )
 {
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites;
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites;
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites;
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites;
+    conf->ciphersuite_list[0] = ciphersuites;
+    conf->ciphersuite_list[1] = ciphersuites;
+    conf->ciphersuite_list[2] = ciphersuites;
+    conf->ciphersuite_list[3] = ciphersuites;
 }
 
 void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf,
@@ -8638,10 +8666,14 @@
     if( major != MBEDTLS_SSL_MAJOR_VERSION_3 )
         return;
 
-    if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 )
+    if( mbedtls_ssl_ver_lt( minor, MBEDTLS_SSL_MINOR_VERSION_0 ) ||
+        mbedtls_ssl_ver_gt( minor, MBEDTLS_SSL_MINOR_VERSION_3 ) )
+    {
         return;
+    }
 
-    conf->ciphersuite_list[minor] = ciphersuites;
+    conf->ciphersuite_list[mbedtls_ssl_minor_ver_index( minor )] =
+        ciphersuites;
 }
 #endif /* MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE */
 
@@ -9395,8 +9427,12 @@
             /* For TLS 1.1 or higher, an explicit IV is added
              * after the record header. */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
-            if( mbedtls_ssl_get_minor_ver( ssl ) >= MBEDTLS_SSL_MINOR_VERSION_2 )
+            if( mbedtls_ssl_ver_geq(
+                    mbedtls_ssl_get_minor_ver( ssl ),
+                    MBEDTLS_SSL_MINOR_VERSION_2 ) )
+            {
                 transform_expansion += block_size;
+            }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
 
             break;
@@ -10070,9 +10106,9 @@
 
     if( session->peer_cert_digest_len != 0 )
     {
-        const mbedtls_md_info_t *md_info =
+        mbedtls_md_handle_t md_info =
             mbedtls_md_info_from_type( session->peer_cert_digest_type );
-        if( md_info == NULL )
+        if( md_info == MBEDTLS_MD_INVALID_HANDLE )
             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
         if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) )
             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -10585,7 +10621,9 @@
 #endif /* MBEDTLS_SSL_PROTO_SSL3 */
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
-                if( mbedtls_ssl_get_minor_ver( ssl ) >= MBEDTLS_SSL_MINOR_VERSION_1 )
+                if( mbedtls_ssl_ver_geq(
+                        mbedtls_ssl_get_minor_ver( ssl ),
+                        MBEDTLS_SSL_MINOR_VERSION_1 ) )
                 {
                     ret = mbedtls_ssl_send_alert_message( ssl,
                                              MBEDTLS_SSL_ALERT_LEVEL_WARNING,
@@ -10793,7 +10831,9 @@
     if( ssl->conf->cbc_record_splitting ==
             MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ||
         len <= 1 ||
-        mbedtls_ssl_get_minor_ver( ssl ) > MBEDTLS_SSL_MINOR_VERSION_1 ||
+        mbedtls_ssl_ver_gt(
+            mbedtls_ssl_get_minor_ver( ssl ),
+            MBEDTLS_SSL_MINOR_VERSION_1 ) ||
         mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc )
                                 != MBEDTLS_MODE_CBC )
     {
@@ -11382,14 +11422,18 @@
      * least check it matches the requirements for serializing.
      */
     if( MBEDTLS_SSL_TRANSPORT_IS_TLS( ssl->conf->transport ) ||
-        mbedtls_ssl_conf_get_max_major_ver( ssl->conf ) <
-            MBEDTLS_SSL_MAJOR_VERSION_3 ||
-        mbedtls_ssl_conf_get_min_major_ver( ssl->conf ) >
-            MBEDTLS_SSL_MAJOR_VERSION_3 ||
-        mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) <
-            MBEDTLS_SSL_MINOR_VERSION_3 ||
-        mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ) >
-            MBEDTLS_SSL_MINOR_VERSION_3 ||
+        mbedtls_ssl_ver_lt(
+            mbedtls_ssl_conf_get_max_major_ver( ssl->conf ),
+            MBEDTLS_SSL_MAJOR_VERSION_3 ) ||
+        mbedtls_ssl_ver_gt(
+            mbedtls_ssl_conf_get_min_major_ver( ssl->conf ),
+            MBEDTLS_SSL_MAJOR_VERSION_3 ) ||
+        mbedtls_ssl_ver_lt(
+            mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ),
+            MBEDTLS_SSL_MINOR_VERSION_3 ) ||
+        mbedtls_ssl_ver_gt(
+            mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ),
+            MBEDTLS_SSL_MINOR_VERSION_3 ) ||
         mbedtls_ssl_conf_is_renegotiation_enabled( ssl->conf ) )
     {
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -11907,11 +11951,11 @@
 #endif /* !MBEDTLS_SSL_CONF_MAX_MINOR_VER */
 
 #if !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE)
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] =
-                                   ssl_preset_suiteb_ciphersuites;
+            conf->ciphersuite_list[0] =
+            conf->ciphersuite_list[1] =
+            conf->ciphersuite_list[2] =
+            conf->ciphersuite_list[3] =
+                ssl_preset_suiteb_ciphersuites;
 #endif /* MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -11959,11 +12003,11 @@
 #endif /* !MBEDTLS_SSL_CONF_MAX_MINOR_VER */
 
 #if !defined(MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE)
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] =
-                                   mbedtls_ssl_list_ciphersuites();
+            conf->ciphersuite_list[0] =
+            conf->ciphersuite_list[1] =
+            conf->ciphersuite_list[2] =
+            conf->ciphersuite_list[3] =
+                mbedtls_ssl_list_ciphersuites();
 #endif /* MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -12427,7 +12471,7 @@
 {
     int ret = 0;
     mbedtls_md_context_t ctx;
-    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
+    mbedtls_md_handle_t md_info = mbedtls_md_info_from_type( md_alg );
     *hashlen = mbedtls_md_get_size( md_info );
 
     mbedtls_md_init( &ctx );
diff --git a/library/version_features.c b/library/version_features.c
index 961148b..4f5bf13 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -579,6 +579,9 @@
 #if defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
     "MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION",
 #endif /* MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
+#if defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+    "MBEDTLS_X509_REMOVE_VERIFY_CALLBACK",
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
     "MBEDTLS_X509_RSASSA_PSS_SUPPORT",
 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
diff --git a/library/x509.c b/library/x509.c
index 19cc64b..d570f71 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -1065,7 +1065,7 @@
     if( pk_alg == MBEDTLS_PK_RSASSA_PSS )
     {
         const mbedtls_pk_rsassa_pss_options *pss_opts;
-        const mbedtls_md_info_t *md_info, *mgf_md_info;
+        mbedtls_md_handle_t md_info, mgf_md_info;
 
         pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
 
@@ -1252,9 +1252,14 @@
 
     ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL,
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
-    NULL,
+                                   NULL,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
-    &flags, NULL, NULL );
+                                   &flags
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+                                   , NULL, NULL
+#endif
+                                   );
+
     if( ret != 0 )
     {
         if( verbose != 0 )
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 0089ef2..dfd9111 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -670,23 +670,6 @@
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
 
 /*
- * Reset (init or clear) a verify_chain
- */
-static void x509_crt_verify_chain_reset(
-    mbedtls_x509_crt_verify_chain *ver_chain )
-{
-    size_t i;
-
-    for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
-    {
-        ver_chain->items[i].crt = NULL;
-        ver_chain->items[i].flags = (uint32_t) -1;
-    }
-
-    ver_chain->len = 0;
-}
-
-/*
  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
  */
 static int x509_get_version( unsigned char **p,
@@ -2088,7 +2071,7 @@
 static int x509_crt_get_sig_info( mbedtls_x509_crt_frame const *frame,
                                   mbedtls_x509_crt_sig_info *info )
 {
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
 
     md_info = mbedtls_md_info_from_type( frame->sig_md );
     if( mbedtls_md( md_info, frame->tbs.p, frame->tbs.len,
@@ -2705,7 +2688,7 @@
     int ret;
     int flags = 0;
     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_x509_buf_raw ca_subject;
     mbedtls_pk_context *pk;
     int can_sign;
@@ -3202,6 +3185,140 @@
     return( -1 );
 }
 
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+
+/*
+ * Reset (init or clear) a verify_chain
+ */
+static void x509_crt_verify_chain_reset(
+    mbedtls_x509_crt_verify_chain *ver_chain )
+{
+    size_t i;
+
+    for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
+    {
+        ver_chain->items[i].crt = NULL;
+        ver_chain->items[i].flags = (uint32_t) -1;
+    }
+
+    ver_chain->len = 0;
+}
+
+/*
+ * Merge the flags for all certs in the chain, after calling callback
+ */
+static int x509_crt_verify_chain_get_flags(
+           const mbedtls_x509_crt_verify_chain *ver_chain,
+           uint32_t *flags,
+           int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+           void *p_vrfy )
+{
+    int ret;
+    unsigned i;
+    uint32_t cur_flags;
+    const mbedtls_x509_crt_verify_chain_item *cur;
+
+    for( i = ver_chain->len; i != 0; --i )
+    {
+        cur = &ver_chain->items[i-1];
+        cur_flags = cur->flags;
+
+        if( NULL != f_vrfy )
+            if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
+                return( ret );
+
+        *flags |= cur_flags;
+    }
+
+    return( 0 );
+}
+
+static void x509_crt_verify_chain_add_ee_flags(
+    mbedtls_x509_crt_verify_chain *chain,
+    uint32_t ee_flags )
+{
+    chain->items[0].flags |= ee_flags;
+}
+
+static void x509_crt_verify_chain_add_crt(
+    mbedtls_x509_crt_verify_chain *chain,
+    mbedtls_x509_crt *crt )
+{
+    mbedtls_x509_crt_verify_chain_item *cur;
+    cur = &chain->items[chain->len];
+    cur->crt = crt;
+    cur->flags = 0;
+    chain->len++;
+}
+
+static uint32_t* x509_crt_verify_chain_get_cur_flags(
+    mbedtls_x509_crt_verify_chain *chain )
+{
+    return( &chain->items[chain->len - 1].flags );
+}
+
+static unsigned x509_crt_verify_chain_len(
+    mbedtls_x509_crt_verify_chain const *chain )
+{
+    return( chain->len );
+}
+
+#else /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+
+/*
+ * Reset (init or clear) a verify_chain
+ */
+static void x509_crt_verify_chain_reset(
+    mbedtls_x509_crt_verify_chain *ver_chain )
+{
+    ver_chain->len   = 0;
+    ver_chain->flags = 0;
+}
+
+/*
+ * Merge the flags for all certs in the chain, after calling callback
+ */
+static int x509_crt_verify_chain_get_flags(
+           const mbedtls_x509_crt_verify_chain *ver_chain,
+           uint32_t *flags,
+           int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+           void *p_vrfy )
+{
+    ((void) f_vrfy);
+    ((void) p_vrfy);
+    *flags = ver_chain->flags;
+    return( 0 );
+}
+
+static void x509_crt_verify_chain_add_ee_flags(
+    mbedtls_x509_crt_verify_chain *chain,
+    uint32_t ee_flags )
+{
+    chain->flags |= ee_flags;
+}
+
+static void x509_crt_verify_chain_add_crt(
+    mbedtls_x509_crt_verify_chain *chain,
+    mbedtls_x509_crt *crt )
+{
+    ((void) crt);
+    chain->len++;
+}
+
+static uint32_t* x509_crt_verify_chain_get_cur_flags(
+    mbedtls_x509_crt_verify_chain *chain )
+{
+    return( &chain->flags );
+}
+
+static unsigned x509_crt_verify_chain_len(
+    mbedtls_x509_crt_verify_chain const *chain )
+{
+    return( chain->len );
+}
+
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+
 /*
  * Build and verify a certificate chain
  *
@@ -3254,7 +3371,6 @@
      * catch potential issues with jumping ahead when restarting */
     int ret;
     uint32_t *flags;
-    mbedtls_x509_crt_verify_chain_item *cur;
     mbedtls_x509_crt *child_crt;
     mbedtls_x509_crt *parent_crt;
     int parent_is_trusted;
@@ -3269,10 +3385,7 @@
         /* restore saved state */
         *ver_chain = rs_ctx->ver_chain; /* struct copy */
         self_cnt = rs_ctx->self_cnt;
-
-        /* restore derived state */
-        cur = &ver_chain->items[ver_chain->len - 1];
-        child_crt = cur->crt;
+        child_crt = rs_ctx->cur_crt;
 
         child_is_trusted = 0;
         goto find_parent;
@@ -3291,16 +3404,13 @@
         int self_issued;
 
         /* Add certificate to the verification chain */
-        cur = &ver_chain->items[ver_chain->len];
-        cur->crt = child_crt;
-        cur->flags = 0;
-        ver_chain->len++;
+        x509_crt_verify_chain_add_crt( ver_chain, child_crt );
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 find_parent:
 #endif
 
-        flags = &cur->flags;
+        flags = x509_crt_verify_chain_get_cur_flags( ver_chain );
 
         {
             mbedtls_x509_crt_sig_info child_sig;
@@ -3342,7 +3452,7 @@
                     *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
 
                 /* Special case: EE certs that are locally trusted */
-                if( ver_chain->len == 1 && self_issued &&
+                if( x509_crt_verify_chain_len( ver_chain ) == 1 && self_issued &&
                     x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
                 {
                     mbedtls_x509_crt_frame_release( child_crt );
@@ -3364,7 +3474,8 @@
             ret = x509_crt_find_parent( &child_sig, child_crt->next,
                                         trust_ca, &parent_crt,
                                         &parent_is_trusted, &signature_is_good,
-                                        ver_chain->len - 1, self_cnt, rs_ctx );
+                                        x509_crt_verify_chain_len( ver_chain ) - 1,
+                                        self_cnt, rs_ctx );
 
             x509_crt_free_sig_info( &child_sig );
         }
@@ -3376,6 +3487,7 @@
             rs_ctx->in_progress = x509_crt_rs_find_parent;
             rs_ctx->self_cnt = self_cnt;
             rs_ctx->ver_chain = *ver_chain; /* struct copy */
+            rs_ctx->cur_crt = child_crt;
             return( ret );
         }
 #else
@@ -3392,13 +3504,14 @@
         /* Count intermediate self-issued (not necessarily self-signed) certs.
          * These can occur with some strategies for key rollover, see [SIRO],
          * and should be excluded from max_pathlen checks. */
-        if( ver_chain->len != 1 && self_issued )
+        if( x509_crt_verify_chain_len( ver_chain ) != 1 && self_issued )
             self_cnt++;
 
         /* path_cnt is 0 for the first intermediate CA,
          * and if parent is trusted it's not an intermediate CA */
         if( ! parent_is_trusted &&
-            ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
+            x509_crt_verify_chain_len( ver_chain ) >
+            MBEDTLS_X509_MAX_INTERMEDIATE_CA )
         {
             /* return immediately to avoid overflow the chain array */
             return( MBEDTLS_ERR_X509_FATAL_ERROR );
@@ -3553,35 +3666,6 @@
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
 
 /*
- * Merge the flags for all certs in the chain, after calling callback
- */
-static int x509_crt_merge_flags_with_cb(
-           uint32_t *flags,
-           const mbedtls_x509_crt_verify_chain *ver_chain,
-           int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-           void *p_vrfy )
-{
-    int ret;
-    unsigned i;
-    uint32_t cur_flags;
-    const mbedtls_x509_crt_verify_chain_item *cur;
-
-    for( i = ver_chain->len; i != 0; --i )
-    {
-        cur = &ver_chain->items[i-1];
-        cur_flags = cur->flags;
-
-        if( NULL != f_vrfy )
-            if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
-                return( ret );
-
-        *flags |= cur_flags;
-    }
-
-    return( 0 );
-}
-
-/*
  * Verify the certificate validity (default profile, not restartable)
  */
 int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
@@ -3590,9 +3674,12 @@
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
                      const char *cn,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
-                     uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy )
+                     uint32_t *flags
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+                     , int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *)
+                     , void *p_vrfy
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+    )
 {
     return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
                 &mbedtls_x509_crt_profile_default,
@@ -3600,7 +3687,10 @@
                 cn,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
                 flags,
-                f_vrfy, p_vrfy, NULL ) );
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+                f_vrfy, p_vrfy,
+#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+                NULL ) );
 }
 
 /*
@@ -3613,16 +3703,23 @@
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
                      const char *cn,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
-                     uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy )
+                     uint32_t *flags
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+                     , int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *)
+                     , void *p_vrfy
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+    )
 {
     return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
                 profile,
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
                 cn,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
-                flags, f_vrfy, p_vrfy, NULL ) );
+                flags,
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+                f_vrfy, p_vrfy,
+#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+                NULL ) );
 }
 
 /*
@@ -3643,8 +3740,10 @@
                      const char *cn,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
                      uint32_t *flags,
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
                      int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
                      void *p_vrfy,
+#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
                      mbedtls_x509_crt_restart_ctx *rs_ctx )
 {
     int ret;
@@ -3699,10 +3798,14 @@
         goto exit;
 
     /* Merge end-entity flags */
-    ver_chain.items[0].flags |= ee_flags;
+    x509_crt_verify_chain_add_ee_flags( &ver_chain, ee_flags );
 
     /* Build final flags, calling callback on the way if any */
-    ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+    ret = x509_crt_verify_chain_get_flags( &ver_chain, flags, f_vrfy, p_vrfy );
+#else
+    ret = x509_crt_verify_chain_get_flags( &ver_chain, flags, NULL, NULL );
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 
 exit:
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index a5acf5b..8d671ab 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -100,7 +100,7 @@
     unsigned char diff;
 
     const mbedtls_cipher_info_t *cipher_info;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_cipher_context_t cipher_ctx;
     mbedtls_md_context_t md_ctx;
 #if defined(_WIN32_WCE)
@@ -192,7 +192,7 @@
     }
 
     md_info = mbedtls_md_info_from_string( argv[5] );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
     {
         mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[5] );
         goto exit;
diff --git a/programs/hash/generic_sum.c b/programs/hash/generic_sum.c
index 709a149..ed5357f 100644
--- a/programs/hash/generic_sum.c
+++ b/programs/hash/generic_sum.c
@@ -53,7 +53,7 @@
 #else
 
 
-static int generic_wrapper( const mbedtls_md_info_t *md_info, char *filename, unsigned char *sum )
+static int generic_wrapper( mbedtls_md_handle_t md_info, char *filename, unsigned char *sum )
 {
     int ret = mbedtls_md_file( md_info, filename, sum );
 
@@ -66,7 +66,7 @@
     return( ret );
 }
 
-static int generic_print( const mbedtls_md_info_t *md_info, char *filename )
+static int generic_print( mbedtls_md_handle_t md_info, char *filename )
 {
     int i;
     unsigned char sum[MBEDTLS_MD_MAX_SIZE];
@@ -81,7 +81,7 @@
     return( 0 );
 }
 
-static int generic_check( const mbedtls_md_info_t *md_info, char *filename )
+static int generic_check( mbedtls_md_handle_t md_info, char *filename )
 {
     int i;
     size_t n;
@@ -177,7 +177,7 @@
 {
     int ret = 1, i;
     int exit_code = MBEDTLS_EXIT_FAILURE;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_md_context_t md_ctx;
 
     mbedtls_md_init( &md_ctx );
@@ -210,7 +210,7 @@
      * Read the MD from the command line
      */
     md_info = mbedtls_md_info_from_string( argv[1] );
-    if( md_info == NULL )
+    if( md_info == MBEDTLS_MD_INVALID_HANDLE )
     {
         mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[1] );
         return( exit_code );
diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c
index 627934f..71a212d 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -1586,6 +1586,14 @@
     }
 #endif /* MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
 
+#if defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+    if( strcmp( "MBEDTLS_X509_REMOVE_VERIFY_CALLBACK", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_X509_REMOVE_VERIFY_CALLBACK );
+        return( 0 );
+    }
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
     if( strcmp( "MBEDTLS_X509_RSASSA_PSS_SUPPORT", config ) == 0 )
     {
@@ -2906,6 +2914,14 @@
     }
 #endif /* MBEDTLS_SSL_CONF_SINGLE_SIG_HASH_TLS_ID */
 
+#if defined(MBEDTLS_MD_SINGLE_HASH)
+    if( strcmp( "MBEDTLS_MD_SINGLE_HASH", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_MD_SINGLE_HASH );
+        return( 0 );
+    }
+#endif /* MBEDTLS_MD_SINGLE_HASH */
+
     /* If the symbol is not found, return an error */
     return( 1 );
 }
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 788793a..1a07c9d 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -69,6 +69,8 @@
 #include "mbedtls/debug.h"
 #include "mbedtls/timing.h"
 
+#include "mbedtls/ssl_internal.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -664,6 +666,8 @@
           !MBEDTLS_SSL_CONF_RECV_TIMEOUT */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
+
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
 static unsigned char peer_crt_info[1024];
 
 /*
@@ -704,6 +708,7 @@
 
     return( 0 );
 }
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
@@ -1506,14 +1511,18 @@
             mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
 
         if( opt.max_version != -1 &&
-            mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info ) > opt.max_version )
+            mbedtls_ssl_ver_gt(
+                mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info ),
+                opt.max_version ) )
         {
             mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" );
             ret = 2;
             goto usage;
         }
         if( opt.min_version != -1 &&
-            mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info ) < opt.min_version )
+            mbedtls_ssl_ver_lt(
+                mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info ),
+                opt.min_version ) )
         {
             mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" );
             ret = 2;
@@ -1523,17 +1532,24 @@
         /* If the server selects a version that's not supported by
          * this suite, then there will be no common ciphersuite... */
         if( opt.max_version == -1 ||
-            opt.max_version > mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info ) )
+            mbedtls_ssl_ver_gt(
+                opt.max_version,
+                mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info ) ) )
         {
             opt.max_version = mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info );
         }
-        if( opt.min_version < mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info ) )
+        if( mbedtls_ssl_ver_lt(
+                opt.min_version,
+                mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info ) ) )
         {
             opt.min_version = mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info );
             /* DTLS starts with TLS 1.1 */
             if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-                opt.min_version < MBEDTLS_SSL_MINOR_VERSION_2 )
+                mbedtls_ssl_ver_lt( opt.min_version,
+                                    MBEDTLS_SSL_MINOR_VERSION_2 ) )
+            {
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2;
+            }
         }
 
         /* Enable RC4 if needed and not explicitly disabled */
@@ -1894,8 +1910,10 @@
 #endif
     }
 
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
     mbedtls_ssl_conf_verify( &conf, my_verify, NULL );
     memset( peer_crt_info, 0, sizeof( peer_crt_info ) );
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
@@ -2316,10 +2334,11 @@
     else
         mbedtls_printf( " ok\n" );
 
-#if !defined(MBEDTLS_X509_REMOVE_INFO)
+#if !defined(MBEDTLS_X509_REMOVE_INFO) && \
+    !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
     mbedtls_printf( "  . Peer certificate information    ...\n" );
     mbedtls_printf( "%s\n", peer_crt_info );
-#endif /* !MBEDTLS_X509_REMOVE_INFO */
+#endif /* !MBEDTLS_X509_REMOVE_INFO && !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
@@ -2648,9 +2667,10 @@
         mbedtls_printf( "  . Restarting connection from same port..." );
         fflush( stdout );
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+    !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
         memset( peer_crt_info, 0, sizeof( peer_crt_info ) );
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 
         if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
         {
@@ -2825,9 +2845,10 @@
 
         mbedtls_printf( "  . Reconnecting with saved session..." );
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+    !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
         memset( peer_crt_info, 0, sizeof( peer_crt_info ) );
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 
         if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
         {
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index b07ab4f..c0476dc 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -68,6 +68,8 @@
 #include "mbedtls/debug.h"
 #include "mbedtls/timing.h"
 
+#include "mbedtls/ssl_internal.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -2232,14 +2234,18 @@
             mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
 
         if( opt.max_version != -1 &&
-            mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info ) > opt.max_version )
+            mbedtls_ssl_ver_gt(
+                mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info ),
+                opt.max_version ) )
         {
             mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" );
             ret = 2;
             goto usage;
         }
         if( opt.min_version != -1 &&
-            mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info ) < opt.min_version )
+            mbedtls_ssl_ver_lt(
+                mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info ),
+                opt.min_version ) )
         {
             mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" );
             ret = 2;
@@ -2249,17 +2255,24 @@
         /* If we select a version that's not supported by
          * this suite, then there will be no common ciphersuite... */
         if( opt.max_version == -1 ||
-            opt.max_version > mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info ) )
+            mbedtls_ssl_ver_gt(
+                opt.max_version,
+                mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info ) ) )
         {
             opt.max_version = mbedtls_ssl_suite_get_max_minor_ver( ciphersuite_info );
         }
-        if( opt.min_version < mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info ) )
+        if( mbedtls_ssl_ver_lt(
+                opt.min_version,
+                mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info ) ) )
         {
             opt.min_version = mbedtls_ssl_suite_get_min_minor_ver( ciphersuite_info );
             /* DTLS starts with TLS 1.1 */
             if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-                opt.min_version < MBEDTLS_SSL_MINOR_VERSION_2 )
+                mbedtls_ssl_ver_lt( opt.min_version,
+                                    MBEDTLS_SSL_MINOR_VERSION_2 ) )
+            {
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2;
+            }
         }
 
         /* Enable RC4 if needed and not explicitly disabled */
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 2b86566..88e3290 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -693,13 +693,16 @@
     if( todo.hmac_drbg )
     {
         mbedtls_hmac_drbg_context hmac_drbg;
-        const mbedtls_md_info_t *md_info;
+        mbedtls_md_handle_t md_info;
 
         mbedtls_hmac_drbg_init( &hmac_drbg );
 
 #if defined(MBEDTLS_SHA1_C)
-        if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL )
+        if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) ==
+            MBEDTLS_MD_INVALID_HANDLE )
+        {
             mbedtls_exit(1);
+        }
 
         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
@@ -715,8 +718,11 @@
 #endif
 
 #if defined(MBEDTLS_SHA256_C)
-        if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ) ) == NULL )
+        if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ) ) ==
+            MBEDTLS_MD_INVALID_HANDLE )
+        {
             mbedtls_exit(1);
+        }
 
         if( mbedtls_hmac_drbg_seed( &hmac_drbg, md_info, myrand, NULL, NULL, 0 ) != 0 )
             mbedtls_exit(1);
diff --git a/programs/test/cpp_dummy_build.cpp b/programs/test/cpp_dummy_build.cpp
index 3c9c278..dcbd5ff 100644
--- a/programs/test/cpp_dummy_build.cpp
+++ b/programs/test/cpp_dummy_build.cpp
@@ -66,7 +66,6 @@
 #include "mbedtls/md2.h"
 #include "mbedtls/md4.h"
 #include "mbedtls/md5.h"
-#include "mbedtls/md_internal.h"
 #include "mbedtls/net.h"
 #include "mbedtls/net_sockets.h"
 #include "mbedtls/nist_kw.h"
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index 74efea3..b82f83f 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -129,6 +129,7 @@
 }
 #endif /* MBEDTLS_DEBUG_C */
 
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
 static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags )
 {
     char buf[1024];
@@ -148,6 +149,7 @@
 
     return( 0 );
 }
+#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 
 #if defined(MBEDTLS_SSL_CONF_RNG)
 int rng_wrap( void *ctx, unsigned char *dst, size_t len );
@@ -363,11 +365,21 @@
         {
             mbedtls_printf( "  . Verifying X.509 certificate..." );
 
-            if( ( ret = mbedtls_x509_crt_verify( &crt, &cacert, &cacrl,
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+            ret = mbedtls_x509_crt_verify( &crt, &cacert, &cacrl,
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
                                         NULL,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
-                                        &flags, my_verify, NULL ) ) != 0 )
+                                        &flags,
+                                        my_verify, NULL );
+#else /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+            ret = mbedtls_x509_crt_verify( &crt, &cacert, &cacrl,
+#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
+                                           NULL,
+#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
+                                           &flags );
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+            if( ret != 0 )
             {
                 char vrfy_buf[512];
 
@@ -436,7 +448,10 @@
         {
             mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED );
             mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
+
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
             mbedtls_ssl_conf_verify( &conf, my_verify, NULL );
+#endif
         }
         else
             mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE );
diff --git a/scripts/config.pl b/scripts/config.pl
index e18df92..287f1f1 100755
--- a/scripts/config.pl
+++ b/scripts/config.pl
@@ -44,6 +44,7 @@
 #   MBEDTLS_X509_CRT_REMOVE_TIME
 #   MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID
 #   MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+#   MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 #   MBEDTLS_ZLIB_SUPPORT
 #   MBEDTLS_PKCS11_C
 #   and any symbol beginning _ALT
@@ -112,6 +113,7 @@
 MBEDTLS_X509_CRT_REMOVE_TIME
 MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID
 MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 MBEDTLS_ZLIB_SUPPORT
 MBEDTLS_PKCS11_C
 MBEDTLS_NO_UDBL_DIVISION
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5938a5f..2ea77e7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -133,6 +133,7 @@
 add_test_suite(shax)
 add_test_suite(ssl)
 add_test_suite(timing)
+add_test_suite(tinycrypt)
 add_test_suite(rsa)
 add_test_suite(version)
 add_test_suite(xtea)
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 1e3287c..977ee9c 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -904,6 +904,34 @@
     if_build_succeeded tests/ssl-opt.sh -f '^Default$\|^Default, DTLS$'
 }
 
+component_test_hardcoded_hash_cmake_clang() {
+    msg "build: cmake, full config + MBEDTLS_MD_SINGLE_HASH, clang" # ~ 50s
+    scripts/config.pl full
+    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+    scripts/config.pl unset MBEDTLS_SHA1_C
+    scripts/config.pl unset MBEDTLS_SHA512_C
+    scripts/config.pl set   MBEDTLS_SHA256_NO_SHA224
+    scripts/config.pl unset MBEDTLS_MD2_C
+    scripts/config.pl unset MBEDTLS_MD4_C
+    scripts/config.pl unset MBEDTLS_MD5_C
+    scripts/config.pl unset MBEDTLS_RIPEMD160_C
+    scripts/config.pl unset MBEDTLS_SSL_PROTO_SSL3
+    scripts/config.pl unset MBEDTLS_SSL_PROTO_TLS1
+    scripts/config.pl unset MBEDTLS_SSL_PROTO_TLS1_1
+    scripts/config.pl unset MBEDTLS_SSL_CBC_RECORD_SPLITTING
+    scripts/config.pl set MBEDTLS_MD_SINGLE_HASH MBEDTLS_MD_INFO_SHA256
+
+    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
+    make
+
+    msg "test: main suites (full config + MBEDTLS_MD_SINGLE_HASH)" # ~ 5s
+    make test
+
+    msg "test: ssl-opt.sh default (full config + MBEDTLS_MD_SINGLE_HASH)" # ~ 5s
+    if_build_succeeded tests/ssl-opt.sh -f '^Default$\|^Default, DTLS$'
+}
+
 component_build_deprecated () {
     msg "build: make, full config + DEPRECATED_WARNING, gcc -O" # ~ 30s
     scripts/config.pl full
@@ -1348,6 +1376,21 @@
     if_build_succeeded tests/ssl-opt.sh
 }
 
+component_test_no_x509_verify_callback () {
+    msg "build: full + MBEDTLS_X509_REMOVE_VERIFY_CALLBACK" # ~ 10s
+    scripts/config.pl full
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
+    scripts/config.pl set MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
+    make CFLAGS='-Werror -O1'
+
+    msg "test: full + MBEDTLS_X509_REMOVE_VERIFY_CALLBACK" # ~ 10s
+    make test
+
+    msg "test: ssl-opt.sh, full + MBEDTLS_X509_REMOVE_VERIFY_CALLBACK" # ~ 1 min
+    if_build_succeeded tests/ssl-opt.sh
+}
+
 component_build_arm_none_eabi_gcc () {
     msg "build: arm-none-eabi-gcc, make" # ~ 10s
     scripts/config.pl baremetal
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index da87793..b0e4515 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -1188,6 +1188,7 @@
 
 requires_config_disabled MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SHA-1 forbidden by default in server certificate" \
             "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt" \
             "$P_CLI debug_level=2 allow_sha1=0" \
@@ -1212,6 +1213,7 @@
 
 requires_config_disabled MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SHA-1 forbidden by default in client certificate" \
             "$P_SRV auth_mode=required allow_sha1=0" \
             "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha1.crt" \
@@ -3653,6 +3655,7 @@
 # Tests for auth_mode
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: server badcert, client required" \
             "$P_SRV crt_file=data_files/server5-badsign.crt \
              key_file=data_files/server5.key" \
@@ -3664,6 +3667,7 @@
             -c "X509 - Certificate verification failed"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: server badcert, client optional" \
             "$P_SRV crt_file=data_files/server5-badsign.crt \
              key_file=data_files/server5.key" \
@@ -3675,6 +3679,7 @@
             -C "X509 - Certificate verification failed"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: server goodcert, client optional, no trusted CA" \
             "$P_SRV" \
             "$P_CLI debug_level=3 auth_mode=optional ca_file=none ca_path=none" \
@@ -3687,6 +3692,7 @@
             -C "SSL - No CA Chain is set, but required to operate"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: server goodcert, client required, no trusted CA" \
             "$P_SRV" \
             "$P_CLI debug_level=3 auth_mode=required ca_file=none ca_path=none" \
@@ -3783,6 +3789,7 @@
             -s "No client certification received from the client, but required by the authentication mode"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: client badcert, server required" \
             "$P_SRV debug_level=3 auth_mode=required" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \
@@ -3805,6 +3812,7 @@
 # before reading the alert message.
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: client cert not trusted, server required" \
             "$P_SRV debug_level=3 auth_mode=required" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-selfsigned.crt \
@@ -3823,6 +3831,7 @@
             -s "X509 - Certificate verification failed"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: client badcert, server optional" \
             "$P_SRV debug_level=3 auth_mode=optional" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \
@@ -3858,6 +3867,7 @@
             -S "X509 - Certificate verification failed"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: client no cert, server optional" \
             "$P_SRV debug_level=3 auth_mode=optional" \
             "$P_CLI debug_level=3 crt_file=none key_file=none" \
@@ -3876,6 +3886,7 @@
             -S "X509 - Certificate verification failed"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: openssl client no cert, server optional" \
             "$P_SRV debug_level=3 auth_mode=optional ca_file=data_files/test-ca2.crt" \
             "$O_CLI" \
@@ -3908,6 +3919,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: client no cert, ssl3" \
             "$P_SRV debug_level=3 auth_mode=optional force_version=ssl3" \
             "$P_CLI debug_level=3 crt_file=none key_file=none min_version=ssl3" \
@@ -4026,6 +4038,7 @@
             -S "requested DN"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Authentication: send CA list in CertificateRequest, client self signed" \
             "$P_SRV debug_level=3 auth_mode=required cert_req_ca_list=0" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-selfsigned.crt \
@@ -4041,6 +4054,7 @@
 # Tests for certificate selection based on SHA verson
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Certificate hash: client TLS 1.2 -> SHA-2" \
             "$P_SRV crt_file=data_files/server5.crt \
                     key_file=data_files/server5.key \
@@ -4052,6 +4066,7 @@
             -C "signed using.*ECDSA with SHA1"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Certificate hash: client TLS 1.1 -> SHA-1" \
             "$P_SRV crt_file=data_files/server5.crt \
                     key_file=data_files/server5.key \
@@ -4063,6 +4078,7 @@
             -c "signed using.*ECDSA with SHA1"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Certificate hash: client TLS 1.0 -> SHA-1" \
             "$P_SRV crt_file=data_files/server5.crt \
                     key_file=data_files/server5.key \
@@ -4074,6 +4090,7 @@
             -c "signed using.*ECDSA with SHA1"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Certificate hash: client TLS 1.1, no SHA-1 -> SHA-2 (order 1)" \
             "$P_SRV crt_file=data_files/server5.crt \
                     key_file=data_files/server5.key \
@@ -4086,6 +4103,7 @@
             -C "signed using.*ECDSA with SHA1"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "Certificate hash: client TLS 1.1, no SHA-1 -> SHA-2 (order 2)" \
             "$P_SRV crt_file=data_files/server6.crt \
                     key_file=data_files/server6.key \
@@ -4100,6 +4118,7 @@
 # tests for SNI
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: no SNI callback" \
             "$P_SRV debug_level=3 \
              crt_file=data_files/server5.crt key_file=data_files/server5.key" \
@@ -4111,6 +4130,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: matching cert 1" \
             "$P_SRV debug_level=3 \
              crt_file=data_files/server5.crt key_file=data_files/server5.key \
@@ -4123,6 +4143,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: matching cert 2" \
             "$P_SRV debug_level=3 \
              crt_file=data_files/server5.crt key_file=data_files/server5.key \
@@ -4189,6 +4210,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: CA no override" \
             "$P_SRV debug_level=3 auth_mode=optional \
              crt_file=data_files/server5.crt key_file=data_files/server5.key \
@@ -4209,6 +4231,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: CA override" \
             "$P_SRV debug_level=3 auth_mode=optional \
              crt_file=data_files/server5.crt key_file=data_files/server5.key \
@@ -4229,6 +4252,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: CA override with CRL" \
             "$P_SRV debug_level=3 auth_mode=optional \
              crt_file=data_files/server5.crt key_file=data_files/server5.key \
@@ -4250,6 +4274,7 @@
 # Tests for SNI and DTLS
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: DTLS, no SNI callback" \
             "$P_SRV debug_level=3 dtls=1 \
              crt_file=data_files/server5.crt key_file=data_files/server5.key" \
@@ -4261,6 +4286,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: DTLS, matching cert 1" \
             "$P_SRV debug_level=3 dtls=1 \
              crt_file=data_files/server5.crt key_file=data_files/server5.key \
@@ -4273,6 +4299,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: DTLS, matching cert 2" \
             "$P_SRV debug_level=3 dtls=1 \
              crt_file=data_files/server5.crt key_file=data_files/server5.key \
@@ -4339,6 +4366,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: DTLS, CA no override" \
             "$P_SRV debug_level=3 auth_mode=optional dtls=1 \
              crt_file=data_files/server5.crt key_file=data_files/server5.key \
@@ -4378,6 +4406,7 @@
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SNI: DTLS, CA override with CRL" \
             "$P_SRV debug_level=3 auth_mode=optional \
              crt_file=data_files/server5.crt key_file=data_files/server5.key dtls=1 \
@@ -4816,6 +4845,7 @@
             -C "Ciphersuite is TLS-"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "keyUsage cli: KeyEncipherment, DHE-RSA: fail, soft" \
             "$O_SRV -key data_files/server2.key \
              -cert data_files/server2.ku-ke.crt" \
@@ -4848,6 +4878,7 @@
             -C "Ciphersuite is TLS-"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "keyUsage cli: DigitalSignature, RSA: fail, soft" \
             "$O_SRV -key data_files/server2.key \
              -cert data_files/server2.ku-ds.crt" \
@@ -6404,16 +6435,14 @@
              crt_file=data_files/server5-badsign.crt \
              key_file=data_files/server5.key" \
             "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
-             key_file=data_files/server5.key crt_file=data_files/server5.crt ca_file=data_files/test-ca2.crt  \
-             debug_level=1 ec_max_ops=1000" \
-            1 \
+             key_file=data_files/server5.key crt_file=data_files/server5.crt ca_file=data_files/test-ca2.crt \
+             debug_level=1 ec_max_ops=1000 auth_mode=optional" \
+            0 \
             -c "x509_verify_cert.*4b00" \
-            -C "mbedtls_pk_verify.*4b00" \
-            -C "mbedtls_ecdh_make_public.*4b00" \
-            -C "mbedtls_pk_sign.*4b00" \
+            -c "mbedtls_pk_verify.*4b00" \
+            -c "mbedtls_ecdh_make_public.*4b00" \
+            -c "mbedtls_pk_sign.*4b00" \
             -c "! The certificate is not correctly signed by the trusted CA" \
-            -c "! mbedtls_ssl_handshake returned" \
-            -c "X509 - Certificate verification failed"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_enabled MBEDTLS_ECP_RESTARTABLE
@@ -6435,6 +6464,7 @@
             -C "X509 - Certificate verification failed"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 requires_config_enabled MBEDTLS_ECP_RESTARTABLE
 run_test    "EC restart: TLS, max_ops=1000, auth_mode=none badsign" \
             "$P_SRV auth_mode=required ca_file=data_files/test-ca2.crt \
@@ -6535,6 +6565,7 @@
 requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
 requires_config_disabled MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "SSL async private: sign, SNI" \
             "$P_SRV debug_level=3 \
              async_operations=s async_private_delay1=0 async_private_delay2=0 \
@@ -6998,6 +7029,7 @@
             -s "Verifying peer X.509 certificate... ok"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "DTLS client auth: optional, client has no cert" \
             "$P_SRV dtls=1 auth_mode=optional" \
             "$P_CLI dtls=1 crt_file=none key_file=none" \
@@ -7005,6 +7037,7 @@
             -s "! Certificate was missing"
 
 requires_config_disabled MBEDTLS_X509_REMOVE_INFO
+requires_config_disabled MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 run_test    "DTLS client auth: none, client has no cert" \
             "$P_SRV dtls=1 auth_mode=none" \
             "$P_CLI dtls=1 crt_file=none key_file=none debug_level=2" \
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index 22d92b6..fa77dfa 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -307,7 +307,7 @@
     mbedtls_mpi d, r, s, r_check, s_check;
     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
     size_t hlen;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
 
     mbedtls_ecp_group_init( &grp );
     mbedtls_mpi_init( &d ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s );
@@ -320,7 +320,7 @@
     TEST_ASSERT( mbedtls_mpi_read_string( &s_check, 16, s_str ) == 0 );
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
     hlen = mbedtls_md_get_size( md_info );
     TEST_ASSERT( mbedtls_md( md_info, (const unsigned char *) msg,
                  strlen( msg ), hash ) == 0 );
@@ -476,7 +476,7 @@
     unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
     unsigned char sig_check[MBEDTLS_ECDSA_MAX_LEN];
     size_t hlen, slen, slen_check;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
 
     mbedtls_ecdsa_restart_init( &rs_ctx );
     mbedtls_ecdsa_init( &ctx );
@@ -489,7 +489,7 @@
     slen_check = unhexify( sig_check, sig_str );
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     hlen = mbedtls_md_get_size( md_info );
     mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash );
diff --git a/tests/suites/test_suite_hkdf.function b/tests/suites/test_suite_hkdf.function
index 3e87207..77f0d5d 100644
--- a/tests/suites/test_suite_hkdf.function
+++ b/tests/suites/test_suite_hkdf.function
@@ -1,6 +1,5 @@
 /* BEGIN_HEADER */
 #include "mbedtls/hkdf.h"
-#include "mbedtls/md_internal.h"
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -25,8 +24,8 @@
      */
     unsigned char okm_hex[257] = { '\0' };
 
-    const mbedtls_md_info_t *md = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md != NULL );
+    mbedtls_md_handle_t md = mbedtls_md_info_from_type( md_alg );
+    TEST_ASSERT( md != MBEDTLS_MD_INVALID_HANDLE );
 
     ikm_len = unhexify( ikm, hex_ikm_string );
     salt_len = unhexify( salt, hex_salt_string );
@@ -54,8 +53,8 @@
     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 );
+    mbedtls_md_handle_t md = mbedtls_md_info_from_type( md_alg );
+    TEST_ASSERT( md != MBEDTLS_MD_INVALID_HANDLE );
 
     output_prk_len = mbedtls_md_get_size( md );
     output_prk = mbedtls_calloc( 1, output_prk_len );
@@ -90,8 +89,8 @@
     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 );
+    mbedtls_md_handle_t md = mbedtls_md_info_from_type( md_alg );
+    TEST_ASSERT( md != MBEDTLS_MD_INVALID_HANDLE );
 
     output_okm = mbedtls_calloc( OKM_LEN, 1 );
 
@@ -114,7 +113,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:!MBEDTLS_MD_SINGLE_HASH */
 void test_hkdf_extract_ret( int hash_len, int ret )
 {
     int output_ret;
@@ -141,7 +140,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:!MBEDTLS_MD_SINGLE_HASH */
 void test_hkdf_expand_ret( int hash_len, int prk_len, int okm_len, int ret )
 {
     int output_ret;
diff --git a/tests/suites/test_suite_hmac_drbg.function b/tests/suites/test_suite_hmac_drbg.function
index 13bc400..da280db 100644
--- a/tests/suites/test_suite_hmac_drbg.function
+++ b/tests/suites/test_suite_hmac_drbg.function
@@ -34,7 +34,7 @@
 {
     unsigned char out[16];
     unsigned char buf[1024];
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_hmac_drbg_context ctx;
     entropy_ctx entropy;
     size_t last_len, i, reps = 10;
@@ -47,7 +47,7 @@
     entropy.p = buf;
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     /* Init must use entropy */
     last_len = entropy.len;
@@ -112,13 +112,13 @@
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
 void hmac_drbg_seed_file( int md_alg, char * path, int ret )
 {
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_hmac_drbg_context ctx;
 
     mbedtls_hmac_drbg_init( &ctx );
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, rnd_std_rand, NULL,
                                  NULL, 0 ) == 0 );
@@ -136,7 +136,7 @@
 {
     unsigned char out[16];
     unsigned char buf[100];
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_hmac_drbg_context ctx;
     size_t i;
 
@@ -145,7 +145,7 @@
     memset( out, 0, sizeof( out ) );
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
     TEST_ASSERT( mbedtls_hmac_drbg_seed_buf( &ctx, md_info, buf, sizeof( buf ) ) == 0 );
 
     /* Make sure it never tries to reseed (would segfault otherwise) */
@@ -168,7 +168,7 @@
     unsigned char data[1024];
     unsigned char my_output[512];
     entropy_ctx p_entropy;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_hmac_drbg_context ctx;
 
     mbedtls_hmac_drbg_init( &ctx );
@@ -177,7 +177,7 @@
     p_entropy.len = entropy->len;
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     /* Test the simplified buffer-based variant */
     memcpy( data, entropy->x, p_entropy.len );
@@ -215,7 +215,7 @@
 {
     unsigned char my_output[512];
     entropy_ctx p_entropy;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_hmac_drbg_context ctx;
 
     mbedtls_hmac_drbg_init( &ctx );
@@ -224,7 +224,7 @@
     p_entropy.len = entropy->len;
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &p_entropy,
                                  custom->x, custom->len ) == 0 );
@@ -247,7 +247,7 @@
 {
     unsigned char my_output[512];
     entropy_ctx p_entropy;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     mbedtls_hmac_drbg_context ctx;
 
     mbedtls_hmac_drbg_init( &ctx );
@@ -256,7 +256,7 @@
     p_entropy.len = entropy->len;
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &p_entropy,
                                  custom->x, custom->len ) == 0 );
diff --git a/tests/suites/test_suite_md.function b/tests/suites/test_suite_md.function
index 11cf88a..31d5aaf 100644
--- a/tests/suites/test_suite_md.function
+++ b/tests/suites/test_suite_md.function
@@ -11,7 +11,7 @@
 void mbedtls_md_process(  )
 {
     const int *md_type_ptr;
-    const mbedtls_md_info_t *info;
+    mbedtls_md_handle_t info;
     mbedtls_md_context_t ctx;
     unsigned char buf[150];
 
@@ -28,7 +28,7 @@
     for( md_type_ptr = mbedtls_md_list(); *md_type_ptr != 0; md_type_ptr++ )
     {
         info = mbedtls_md_info_from_type( *md_type_ptr );
-        TEST_ASSERT( info != NULL );
+        TEST_ASSERT( info != MBEDTLS_MD_INVALID_HANDLE );
         TEST_ASSERT( mbedtls_md_setup( &ctx, info, 0 ) == 0 );
         TEST_ASSERT( mbedtls_md_process( &ctx, buf ) == 0 );
         mbedtls_md_free( &ctx );
@@ -39,22 +39,26 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:!MBEDTLS_MD_SINGLE_HASH */
 void md_null_args(  )
 {
     mbedtls_md_context_t ctx;
-    const mbedtls_md_info_t *info = mbedtls_md_info_from_type( *( mbedtls_md_list() ) );
+    mbedtls_md_handle_t info = mbedtls_md_info_from_type( *( mbedtls_md_list() ) );
     unsigned char buf[1] = { 0 };
 
     mbedtls_md_init( &ctx );
 
-    TEST_ASSERT( mbedtls_md_get_size( NULL ) == 0 );
-    TEST_ASSERT( mbedtls_md_get_type( NULL ) == MBEDTLS_MD_NONE );
-    TEST_ASSERT( mbedtls_md_get_name( NULL ) == NULL );
+    TEST_ASSERT( mbedtls_md_get_size( MBEDTLS_MD_INVALID_HANDLE )
+                 == 0 );
+    TEST_ASSERT( mbedtls_md_get_type( MBEDTLS_MD_INVALID_HANDLE )
+                 == MBEDTLS_MD_NONE );
+    TEST_ASSERT( mbedtls_md_get_name( MBEDTLS_MD_INVALID_HANDLE )
+                 == NULL );
 
-    TEST_ASSERT( mbedtls_md_info_from_string( NULL ) == NULL );
+    TEST_ASSERT( mbedtls_md_info_from_string( NULL ) == MBEDTLS_MD_INVALID_HANDLE );
 
-    TEST_ASSERT( mbedtls_md_setup( &ctx, NULL, 0 ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_md_setup( &ctx, MBEDTLS_MD_INVALID_HANDLE, 0 )
+                 == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
     TEST_ASSERT( mbedtls_md_setup( NULL, info, 0 ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
     TEST_ASSERT( mbedtls_md_starts( NULL ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
@@ -66,10 +70,12 @@
     TEST_ASSERT( mbedtls_md_finish( NULL, buf ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
     TEST_ASSERT( mbedtls_md_finish( &ctx, buf ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    TEST_ASSERT( mbedtls_md( NULL, buf, 1, buf ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_md( MBEDTLS_MD_INVALID_HANDLE,
+                             buf, 1, buf ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
 #if defined(MBEDTLS_FS_IO)
-    TEST_ASSERT( mbedtls_md_file( NULL, "", buf ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    TEST_ASSERT( mbedtls_md_file( MBEDTLS_MD_INVALID_HANDLE,
+                                  "", buf ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 #endif
 
     TEST_ASSERT( mbedtls_md_hmac_starts( NULL, buf, 1 )
@@ -90,27 +96,29 @@
     TEST_ASSERT( mbedtls_md_hmac_reset( NULL ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
     TEST_ASSERT( mbedtls_md_hmac_reset( &ctx ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-    TEST_ASSERT( mbedtls_md_hmac( NULL, buf, 1, buf, 1, buf )
+    TEST_ASSERT( mbedtls_md_hmac( MBEDTLS_MD_INVALID_HANDLE, buf, 1, buf, 1, buf )
                  == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
     TEST_ASSERT( mbedtls_md_process( NULL, buf ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
     TEST_ASSERT( mbedtls_md_process( &ctx, buf ) == MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
     /* Ok, this is not NULL arg but NULL return... */
-    TEST_ASSERT( mbedtls_md_info_from_type( MBEDTLS_MD_NONE ) == NULL );
-    TEST_ASSERT( mbedtls_md_info_from_string( "no such md" ) == NULL );
+    TEST_ASSERT( mbedtls_md_info_from_type( MBEDTLS_MD_NONE ) ==
+                 MBEDTLS_MD_INVALID_HANDLE );
+    TEST_ASSERT( mbedtls_md_info_from_string( "no such md" ) ==
+                 MBEDTLS_MD_INVALID_HANDLE );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
 void md_info( int md_type, char * md_name, int md_size )
 {
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
     const int *md_type_ptr;
     int found;
 
     md_info = mbedtls_md_info_from_type( md_type );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
     TEST_ASSERT( md_info == mbedtls_md_info_from_string( md_name ) );
 
     TEST_ASSERT( mbedtls_md_get_type( md_info ) == (mbedtls_md_type_t) md_type );
@@ -132,7 +140,7 @@
     char md_name[100];
     unsigned char src_str[1000];
     unsigned char output[100];
-    const mbedtls_md_info_t *md_info = NULL;
+    mbedtls_md_handle_t md_info = MBEDTLS_MD_INVALID_HANDLE;
 
     memset( md_name, 0x00, 100 );
     memset( src_str, 0x00, 1000 );
@@ -141,7 +149,7 @@
     strncpy( (char *) src_str, text_src_string, sizeof( src_str ) - 1 );
     strncpy( (char *) md_name, text_md_name, sizeof( md_name ) - 1 );
     md_info = mbedtls_md_info_from_string(md_name);
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     TEST_ASSERT ( 0 == mbedtls_md( md_info, src_str, strlen( (char *) src_str ), output ) );
 
@@ -155,14 +163,14 @@
 {
     char md_name[100];
     unsigned char output[100];
-    const mbedtls_md_info_t *md_info = NULL;
+    mbedtls_md_handle_t md_info = MBEDTLS_MD_INVALID_HANDLE;
 
     memset( md_name, 0x00, 100 );
     memset( output, 0x00, 100 );
 
     strncpy( (char *) md_name, text_md_name, sizeof( md_name ) - 1 );
     md_info = mbedtls_md_info_from_string( md_name );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     TEST_ASSERT ( 0 == mbedtls_md( md_info, src_str->x, src_str->len, output ) );
 
@@ -181,7 +189,7 @@
     unsigned char output[100];
     int halfway, len;
 
-    const mbedtls_md_info_t *md_info = NULL;
+    mbedtls_md_handle_t md_info = MBEDTLS_MD_INVALID_HANDLE;
     mbedtls_md_context_t ctx, ctx_copy;
 
     mbedtls_md_init( &ctx );
@@ -197,7 +205,7 @@
     halfway = len / 2;
 
     md_info = mbedtls_md_info_from_string(md_name);
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
     TEST_ASSERT ( 0 == mbedtls_md_setup( &ctx, md_info, 0 ) );
     TEST_ASSERT ( 0 == mbedtls_md_setup( &ctx_copy, md_info, 0 ) );
 
@@ -230,7 +238,7 @@
 {
     char md_name[100];
     unsigned char output[100];
-    const mbedtls_md_info_t *md_info = NULL;
+    mbedtls_md_handle_t md_info = MBEDTLS_MD_INVALID_HANDLE;
     mbedtls_md_context_t ctx, ctx_copy;
     int halfway;
 
@@ -242,7 +250,7 @@
 
     strncpy( (char *) md_name, text_md_name, sizeof( md_name ) - 1 );
     md_info = mbedtls_md_info_from_string(md_name);
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
     TEST_ASSERT ( 0 == mbedtls_md_setup( &ctx, md_info, 0 ) );
     TEST_ASSERT ( 0 == mbedtls_md_setup( &ctx_copy, md_info, 0 ) );
 
@@ -277,14 +285,14 @@
 {
     char md_name[100];
     unsigned char output[100];
-    const mbedtls_md_info_t *md_info = NULL;
+    mbedtls_md_handle_t md_info = MBEDTLS_MD_INVALID_HANDLE;
 
     memset( md_name, 0x00, 100 );
     memset( output, 0x00, 100 );
 
     strncpy( (char *) md_name, text_md_name, sizeof( md_name ) - 1 );
     md_info = mbedtls_md_info_from_string( md_name );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
 
     TEST_ASSERT ( mbedtls_md_hmac( md_info, key_str->x, key_str->len, src_str->x, src_str->len, output ) == 0 );
@@ -299,7 +307,7 @@
 {
     char md_name[100];
     unsigned char output[100];
-    const mbedtls_md_info_t *md_info = NULL;
+    mbedtls_md_handle_t md_info = MBEDTLS_MD_INVALID_HANDLE;
     mbedtls_md_context_t ctx;
     int halfway;
 
@@ -310,7 +318,7 @@
 
     strncpy( (char *) md_name, text_md_name, sizeof( md_name ) - 1 );
     md_info = mbedtls_md_info_from_string( md_name );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
     TEST_ASSERT ( 0 == mbedtls_md_setup( &ctx, md_info, 1 ) );
 
     halfway = src_str->len / 2;
@@ -344,14 +352,14 @@
 {
     char md_name[100];
     unsigned char output[100];
-    const mbedtls_md_info_t *md_info = NULL;
+    mbedtls_md_handle_t md_info = MBEDTLS_MD_INVALID_HANDLE;
 
     memset( md_name, 0x00, 100 );
     memset( output, 0x00, 100 );
 
     strncpy( (char *) md_name, text_md_name, sizeof( md_name ) - 1 );
     md_info = mbedtls_md_info_from_string( md_name );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     TEST_ASSERT( mbedtls_md_file( md_info, filename, output ) == 0 );
 
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 8b95bab..fc917d0 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -593,7 +593,7 @@
     TEST_ASSERT( mbedtls_mpi_read_string( &rsa->E, radix_E, input_E ) == 0 );
 
 
-    if( mbedtls_md_info_from_type( digest ) != NULL )
+    if( mbedtls_md_info_from_type( digest ) != MBEDTLS_MD_INVALID_HANDLE )
         TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 );
 
     TEST_ASSERT( mbedtls_pk_verify( &pk, digest, hash_result, 0,
@@ -709,7 +709,7 @@
     unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
     unsigned char sig_check[MBEDTLS_ECDSA_MAX_LEN];
     size_t hlen, slen, slen_check;
-    const mbedtls_md_info_t *md_info;
+    mbedtls_md_handle_t md_info;
 
     mbedtls_pk_restart_init( &rs_ctx );
     mbedtls_pk_init( &prv );
@@ -729,7 +729,7 @@
     slen_check = unhexify( sig_check, sig_str );
 
     md_info = mbedtls_md_info_from_type( md_alg );
-    TEST_ASSERT( md_info != NULL );
+    TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
     hlen = mbedtls_md_get_size( md_info );
     mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash );
diff --git a/tests/suites/test_suite_pkcs1_v15.function b/tests/suites/test_suite_pkcs1_v15.function
index 0723623..58c25bf 100644
--- a/tests/suites/test_suite_pkcs1_v15.function
+++ b/tests/suites/test_suite_pkcs1_v15.function
@@ -275,8 +275,10 @@
     TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
 
 
-    if( mbedtls_md_info_from_type( digest ) != NULL )
+    if( mbedtls_md_info_from_type( digest ) != MBEDTLS_MD_INVALID_HANDLE )
+    {
         TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 );
+    }
 
     TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &rnd_buffer_rand, &info, MBEDTLS_RSA_PRIVATE, digest, 0, hash_result, output ) == result );
     if( result == 0 )
@@ -313,9 +315,10 @@
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
 
-
-    if( mbedtls_md_info_from_type( digest ) != NULL )
+    if( mbedtls_md_info_from_type( digest ) != MBEDTLS_MD_INVALID_HANDLE )
+    {
         TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 );
+    }
 
     TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, digest, 0, hash_result, result_str->x ) == result );
 
diff --git a/tests/suites/test_suite_pkcs1_v21.function b/tests/suites/test_suite_pkcs1_v21.function
index 99be08a..a9635e1 100644
--- a/tests/suites/test_suite_pkcs1_v21.function
+++ b/tests/suites/test_suite_pkcs1_v21.function
@@ -128,8 +128,10 @@
     TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
 
 
-    if( mbedtls_md_info_from_type( digest ) != NULL )
+    if( mbedtls_md_info_from_type( digest ) != MBEDTLS_MD_INVALID_HANDLE )
+    {
         TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 );
+    }
 
     TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &rnd_buffer_rand, &info, MBEDTLS_RSA_PRIVATE,
                                          digest, 0, hash_result, output ) == result );
@@ -169,8 +171,10 @@
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
 
 
-    if( mbedtls_md_info_from_type( digest ) != NULL )
+    if( mbedtls_md_info_from_type( digest ) != MBEDTLS_MD_INVALID_HANDLE )
+    {
         TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 );
+    }
 
     TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, digest, 0, hash_result, result_str->x ) == result );
 
diff --git a/tests/suites/test_suite_pkcs5.function b/tests/suites/test_suite_pkcs5.function
index 26f1d33..a8f0523 100644
--- a/tests/suites/test_suite_pkcs5.function
+++ b/tests/suites/test_suite_pkcs5.function
@@ -12,14 +12,14 @@
                   int it_cnt, int key_len, data_t * result_key_string )
 {
     mbedtls_md_context_t ctx;
-    const mbedtls_md_info_t *info;
+    mbedtls_md_handle_t info;
 
     unsigned char key[100];
 
     mbedtls_md_init( &ctx );
 
     info = mbedtls_md_info_from_type( hash );
-    TEST_ASSERT( info != NULL );
+    TEST_ASSERT( info != MBEDTLS_MD_INVALID_HANDLE );
     TEST_ASSERT( mbedtls_md_setup( &ctx, info, 1 ) == 0 );
     TEST_ASSERT( mbedtls_pkcs5_pbkdf2_hmac( &ctx, pw_str->x, pw_str->len, salt_str->x, salt_str->len,
                                      it_cnt, key_len, key ) == 0 );
diff --git a/tests/suites/test_suite_rsa.function b/tests/suites/test_suite_rsa.function
index f2a9b98..4d22c9b 100644
--- a/tests/suites/test_suite_rsa.function
+++ b/tests/suites/test_suite_rsa.function
@@ -497,8 +497,10 @@
     TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
 
 
-    if( mbedtls_md_info_from_type( digest ) != NULL )
+    if( mbedtls_md_info_from_type( digest ) != MBEDTLS_MD_INVALID_HANDLE )
+    {
         TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 );
+    }
 
     TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &rnd_pseudo_rand, &rnd_info,
                                          MBEDTLS_RSA_PRIVATE, digest, 0,
@@ -538,8 +540,10 @@
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
 
 
-    if( mbedtls_md_info_from_type( digest ) != NULL )
+    if( mbedtls_md_info_from_type( digest ) != MBEDTLS_MD_INVALID_HANDLE )
+    {
         TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 );
+    }
 
     TEST_ASSERT( mbedtls_rsa_pkcs1_verify( &ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, digest, 0, hash_result, result_str->x ) == result );
 
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index b177779..9873dd8 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -102,12 +102,12 @@
     if( cipher_info->mode == MBEDTLS_MODE_CBC ||
         cipher_info->mode == MBEDTLS_MODE_STREAM )
     {
-        mbedtls_md_info_t const *md_info;
+        mbedtls_md_handle_t md_info;
         unsigned char *md0, *md1;
 
         /* Pick hash */
         md_info = mbedtls_md_info_from_type( hash_id );
-        CHK( md_info != NULL );
+        CHK( md_info != MBEDTLS_MD_INVALID_HANDLE );
 
         /* Pick hash keys */
         maclen = mbedtls_md_get_size( md_info );
@@ -121,7 +121,7 @@
         CHK( mbedtls_md_setup( &t_in->md_ctx_enc,  md_info, 1 ) == 0 );
         CHK( mbedtls_md_setup( &t_in->md_ctx_dec,  md_info, 1 ) == 0 );
 
-        if( ver > MBEDTLS_SSL_MINOR_VERSION_0 )
+        if( mbedtls_ssl_ver_gt( ver, MBEDTLS_SSL_MINOR_VERSION_0 ) )
         {
             CHK( mbedtls_md_hmac_starts( &t_in->md_ctx_enc,
                                          md0, maclen ) == 0 );
diff --git a/tests/suites/test_suite_tinycrypt.data b/tests/suites/test_suite_tinycrypt.data
new file mode 100644
index 0000000..ac2a8e2
--- /dev/null
+++ b/tests/suites/test_suite_tinycrypt.data
@@ -0,0 +1,11 @@
+Tinycrypt ECDH
+test_ecdh:
+
+Tinycrypt ECDSA
+test_ecdsa:
+
+ECDH primitive rfc 5903 p256
+ecdh_primitive_testvec:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"DAD0B65394221CF9B051E1FECA5787D098DFE637FC90B9EF945D0C3772581180":"5271A0461CDB8252D61F1C456FA3E59AB1F45B33ACCF5F58389E0577B8990BB3":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D12DFB5289C8D4F81208B70270398C342296970A0BCCB74C736FC7554494BF63":"56FBF3CA366CC23E8157854C13C58D6AAC23F046ADA30F8353E74F33039872AB":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE"
+
+ECDSA primitive rfc 4754 p256
+ecdsa_primitive_testvec:"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":"BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD":"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"86FA3BB4E26CAD5BF90B7F81899256CE7594BB1EA0C89212748BFF3B3D5B0315":1
diff --git a/tests/suites/test_suite_tinycrypt.function b/tests/suites/test_suite_tinycrypt.function
new file mode 100644
index 0000000..24b331d
--- /dev/null
+++ b/tests/suites/test_suite_tinycrypt.function
@@ -0,0 +1,117 @@
+/* BEGIN_HEADER */
+
+#include "tinycrypt/ecc.h"
+#include "tinycrypt/ecc_dh.h"
+#include "tinycrypt/ecc_dsa.h"
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_USE_TINYCRYPT
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDTLS_USE_TINYCRYPT */
+void test_ecdh()
+{
+    uint8_t private1[NUM_ECC_BYTES] = {0};
+    uint8_t private2[NUM_ECC_BYTES] = {0};
+    uint8_t public1[2*NUM_ECC_BYTES] = {0};
+    uint8_t public2[2*NUM_ECC_BYTES] = {0};
+    uint8_t secret1[NUM_ECC_BYTES] = {0};
+    uint8_t secret2[NUM_ECC_BYTES] = {0};
+
+    const struct uECC_Curve_t * curve = uECC_secp256r1();
+
+    uECC_set_rng( &uecc_rng_wrapper );
+
+    TEST_ASSERT( uECC_make_key( public1, private1, curve ) != 0 );
+
+    TEST_ASSERT( uECC_make_key( public2, private2, curve ) != 0 );
+
+    TEST_ASSERT( uECC_shared_secret( public2, private1, secret1, curve ) != 0 );
+
+    TEST_ASSERT( uECC_shared_secret( public1, private2, secret2, curve ) != 0 );
+
+    TEST_ASSERT( memcmp( secret1, secret2, sizeof( secret1 ) ) == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_USE_TINYCRYPT */
+void test_ecdsa()
+{
+    uint8_t private[NUM_ECC_BYTES] = {0};
+    uint8_t public[2*NUM_ECC_BYTES] = {0};
+    uint8_t hash[NUM_ECC_BYTES] = {0};
+    uint8_t sig[2*NUM_ECC_BYTES] = {0};
+
+    const struct uECC_Curve_t * curve = uECC_secp256r1();
+
+    uECC_set_rng( &uecc_rng_wrapper );
+
+    TEST_ASSERT( rnd_std_rand( NULL, hash, NUM_ECC_BYTES ) == 0 );
+
+    TEST_ASSERT( uECC_make_key( public, private, curve ) != 0 );
+
+    TEST_ASSERT( uECC_sign( private, hash, sizeof( hash ), sig, curve ) != 0 );
+
+    TEST_ASSERT( uECC_verify( public, hash, sizeof( hash ), sig, curve ) != 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_USE_TINYCRYPT */
+void ecdh_primitive_testvec( data_t * private1, data_t * xA_str,
+                             data_t * yA_str, data_t * private2,
+                             data_t * xB_str, data_t * yB_str, data_t * z_str )
+{
+    const struct uECC_Curve_t * curve = uECC_secp256r1();
+    uint8_t public1[2*NUM_ECC_BYTES] = {0};
+    uint8_t public2[2*NUM_ECC_BYTES] = {0};
+    uint8_t secret1[NUM_ECC_BYTES] = {0};
+    uint8_t secret2[NUM_ECC_BYTES] = {0};
+
+    memcpy( public1, xA_str->x, xA_str->len );
+    memcpy( public1 + NUM_ECC_BYTES, yA_str->x, yA_str->len );
+    memcpy( public2, xB_str->x, xB_str->len );
+    memcpy( public2 + NUM_ECC_BYTES, yB_str->x, yB_str->len );
+
+    // Compute shared secrets and compare to test vector secret
+    TEST_ASSERT( uECC_shared_secret( public2, private1->x, secret1, curve ) != 0 );
+
+    TEST_ASSERT( uECC_shared_secret( public1, private2->x, secret2, curve ) != 0 );
+
+    TEST_ASSERT( memcmp( secret1, secret2, sizeof( secret1 ) ) == 0 );
+    TEST_ASSERT( memcmp( secret1, z_str->x, sizeof( secret1 ) ) == 0 );
+    TEST_ASSERT( memcmp( secret2, z_str->x, sizeof( secret2 ) ) == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_USE_TINYCRYPT */
+void ecdsa_primitive_testvec( data_t * xQ_str, data_t * yQ_str,
+                              data_t * hash, data_t * r_str, data_t * s_str,
+                              int result )
+{
+    const struct uECC_Curve_t * curve = uECC_secp256r1();
+    uint8_t pub_bytes[2*NUM_ECC_BYTES] = {0};
+    uint8_t sig_bytes[2*NUM_ECC_BYTES] = {0};
+
+    memcpy( pub_bytes, xQ_str->x, xQ_str->len );
+    memcpy( pub_bytes + NUM_ECC_BYTES, yQ_str->x, yQ_str->len );
+    memcpy( sig_bytes, r_str->x, r_str->len );
+    memcpy( sig_bytes + NUM_ECC_BYTES, s_str->x, r_str->len );
+
+    TEST_ASSERT( uECC_verify( pub_bytes, hash->x, hash->len,
+                              sig_bytes, curve ) == result );
+
+    // Alter the signature and check the verification fails
+    for( int i = 0; i < 2*NUM_ECC_BYTES; i++ )
+    {
+        uint8_t temp = sig_bytes[i];
+        sig_bytes[i] = ( sig_bytes[i] + 1 ) % 256;
+        TEST_ASSERT( uECC_verify( pub_bytes, hash->x, hash->len,
+                                  sig_bytes, curve ) == 0 );
+        sig_bytes[i] = temp;
+    }
+
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 4542440..abf2ab3 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -560,11 +560,11 @@
 x509_verify:"data_files/cert_sha512.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"compat":"NULL"
 
 X509 CRT verification #19 (Valid Cert, denying callback)
-depends_on:MBEDTLS_SHA512_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_SHA512_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:!MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 x509_verify:"data_files/cert_sha512.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_OTHER:"compat":"verify_none"
 
 X509 CRT verification #19 (Not trusted Cert, allowing callback)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA1_C
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA1_C:!MBEDTLS_X509_REMOVE_VERIFY_CALLBACK:!MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 x509_verify:"data_files/server2.crt":"data_files/server1.crt":"data_files/crl_expired.pem":"NULL":0:0:"compat":"verify_all"
 
 X509 CRT verification #21 (domain matching wildcard certificate, case insensitive)
@@ -920,7 +920,7 @@
 x509_verify:"data_files/server1.crt":"data_files/test-ca-alt-good.crt":"data_files/crl-ec-sha256.pem":"NULL":0:0:"compat":"NULL"
 
 X509 CRT verification #92 (bad name, allowing callback)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:!MBEDTLS_USE_TINYCRYPT
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:!MBEDTLS_USE_TINYCRYPT:!MBEDTLS_X509_REMOVE_VERIFY_CALLBACK
 x509_verify:"data_files/server5.crt":"data_files/test-ca2.crt":"data_files/crl-ec-sha256.pem":"globalhost":0:0:"":"verify_all"
 
 X509 CRT verification #93 (Suite B invalid, EC cert, RSA CA)
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index 96ad7d9..130d90f 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -334,7 +334,10 @@
                 NULL,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
                 &flags,
-                NULL, NULL, &rs_ctx );
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+                NULL, NULL,
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+                &rs_ctx );
     } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart );
 
     TEST_ASSERT( ret == result );
@@ -355,7 +358,10 @@
             NULL,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
             &flags,
-            NULL, NULL, &rs_ctx );
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
+            NULL, NULL,
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+            &rs_ctx );
     TEST_ASSERT( ret == result || ret == MBEDTLS_ERR_ECP_IN_PROGRESS );
 
 exit:
@@ -376,7 +382,9 @@
     mbedtls_x509_crl    crl;
     uint32_t         flags = 0;
     int         res;
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *) = NULL;
+#endif
     const mbedtls_x509_crt_profile *profile;
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
     char *      cn_name = NULL;
@@ -406,6 +414,7 @@
     else
         TEST_ASSERT( "Unknown algorithm profile" == 0 );
 
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
     if( strcmp( verify_callback, "NULL" ) == 0 )
         f_vrfy = NULL;
     else if( strcmp( verify_callback, "verify_none" ) == 0 )
@@ -414,16 +423,28 @@
         f_vrfy = verify_all;
     else
         TEST_ASSERT( "No known verify callback selected" == 0 );
+#else
+    if( strcmp( verify_callback, "NULL" ) != 0 )
+        TEST_ASSERT( "Verify callbacks disabled" == 0 );
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &ca, ca_file ) == 0 );
     TEST_ASSERT( mbedtls_x509_crl_parse_file( &crl, crl_file ) == 0 );
 
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
     res = mbedtls_x509_crt_verify_with_profile( &crt, &ca, &crl, profile,
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
                                                 cn_name,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
                                                 &flags, f_vrfy, NULL );
+#else
+    res = mbedtls_x509_crt_verify_with_profile( &crt, &ca, &crl, profile,
+#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
+                                                cn_name,
+#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
+                                                &flags );
+#endif
 
     TEST_ASSERT( res == ( result ) );
     if( flags != (uint32_t) flags_result )
@@ -441,7 +462,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 void x509_verify_callback( char *crt_file, char *ca_file, char *name,
                            int exp_ret, char *exp_vrfy_out )
 {
@@ -827,11 +848,21 @@
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &chain, file_buf ) == 0 );
 
     /* Try to verify that chain */
+#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
     ret = mbedtls_x509_crt_verify( &chain, &trusted, NULL,
 #if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
                                    NULL,
 #endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
-                                   &flags, NULL, NULL );
+                                   &flags,
+                                   NULL, NULL );
+#else
+    ret = mbedtls_x509_crt_verify( &chain, &trusted, NULL,
+#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
+                                   NULL,
+#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
+                                   &flags );
+#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
+
     TEST_ASSERT( ret == ret_chk );
     TEST_ASSERT( flags == (uint32_t) flags_chk );
 
@@ -841,7 +872,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
 void mbedtls_x509_crt_verify_chain(  char *chain_paths, char *trusted_ca,
                                      int flags_result, int result,
                                      char *profile_name, int vrfy_fatal_lvls )
diff --git a/tinycrypt/LICENSE b/tinycrypt/LICENSE
new file mode 100644
index 0000000..2e1db51
--- /dev/null
+++ b/tinycrypt/LICENSE
@@ -0,0 +1,61 @@
+
+================================================================================
+
+                     TinyCrypt Cryptographic Library                       
+
+================================================================================
+
+          Copyright (c) 2017, Intel Corporation. All rights reserved.         
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+  - Redistributions of source code must retain the above copyright notice, this 
+      list of conditions and the following disclaimer.
+      
+  - Redistributions in binary form must reproduce the above copyright notice, 
+      this list of conditions and the following disclaimer in the documentation 
+      and/or other materials provided with the distribution.
+      
+  - Neither the name of the Intel Corporation nor the names of its contributors 
+      may be used to endorse or promote products derived from this software 
+      without specific prior written permission. 
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
+Copyright (c) 2014, Kenneth MacKay
+All rights reserved.
+
+https://github.com/kmackay/micro-ecc
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
diff --git a/tinycrypt/README b/tinycrypt/README
new file mode 100644
index 0000000..d0f49a6
--- /dev/null
+++ b/tinycrypt/README
@@ -0,0 +1,77 @@
+
+================================================================================
+
+                     TinyCrypt Cryptographic Library
+                    (integrated as  part of Mbed TLS)
+
+================================================================================
+
+          Copyright (c) 2017, Intel Corporation. All rights reserved.         
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+  - Redistributions of source code must retain the above copyright notice, this 
+      list of conditions and the following disclaimer.
+      
+  - Redistributions in binary form must reproduce the above copyright notice, 
+      this list of conditions and the following disclaimer in the documentation 
+      and/or other materials provided with the distribution.
+      
+  - Neither the name of the Intel Corporation nor the names of its contributors 
+      may be used to endorse or promote products derived from this software 
+      without specific prior written permission. 
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
+
+Copyright (c) 2019 ARM Limited
+
+================================================================================
+Overview:
+
+The TinyCrypt Library provides an implementation for constrained devices of a 
+minimal set of standard cryptography primitives. 
+
+This is a modified form of the library based on version 0.2.8 included as part
+of Mbed TLS as a compilation option. It is not included in its full form and
+those wishing to use TinyCrypt should use the original unmodified project.
+
+The original project can be found here: https://github.com/intel/tinycrypt
+
+Contributions should be made upstream to that project, and full documentation 
+can be found in the originating repository.
+
+================================================================================
+
+Organization:
+
+tinycrypt: C source code of the cryptographic primitives.
+include/tinycrypt: C header files of the cryptographic primitives.
+
+No documentation is provided, and instead is available with the original
+project.
+
+Tests are provided as part of Mbed TLS and the Mbed TLS test suites.
+
+================================================================================
+
+Building:
+
+To include TinyCrypt as part of Mbed TLS, enable the configuration option
+MBEDTLS_USE_TINYCRYPT in the configration file 'include/mbedtls/config.h', and
+build as Mbed TLS as normal.
+
+================================================================================
+
diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c
index ab1956a..cef1469 100644
--- a/tinycrypt/ecc.c
+++ b/tinycrypt/ecc.c
@@ -1,6 +1,11 @@
 /* ecc.c - TinyCrypt implementation of common ECC functions */
 
 /*
+ *  Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved.
+ *  SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
  * Copyright (c) 2014, Kenneth MacKay
  * All rights reserved.
  *
diff --git a/tinycrypt/ecc_dh.c b/tinycrypt/ecc_dh.c
index 8aae1a2..ec1328e 100644
--- a/tinycrypt/ecc_dh.c
+++ b/tinycrypt/ecc_dh.c
@@ -1,6 +1,11 @@
 /* ec_dh.c - TinyCrypt implementation of EC-DH */
 
 /*
+ *  Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved.
+ *  SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
  * Copyright (c) 2014, Kenneth MacKay
  * All rights reserved.
  *
diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c
index 3743091..a3893d3 100644
--- a/tinycrypt/ecc_dsa.c
+++ b/tinycrypt/ecc_dsa.c
@@ -1,5 +1,10 @@
 /* ec_dsa.c - TinyCrypt implementation of EC-DSA */
 
+/*
+ *  Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved.
+ *  SPDX-License-Identifier: BSD-3-Clause
+ */
+
 /* Copyright (c) 2014, Kenneth MacKay
  * All rights reserved.
  *
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 2ec9178..e6f9ec8 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -264,7 +264,6 @@
     <ClCompile Include="..\..\library\md2.c" />

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

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

-    <ClCompile Include="..\..\library\md_wrap.c" />

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

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

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