Introduce md_internal.h

Recall that in the default configuration, Mbed TLS provides access
digest implementations through two layers of indirection:

1) Call of MD API (e.g. mbedtls_md_update())
2) Call of function pointer from MD info structure
3) Actual digest implementation (e.g. mbedtls_sha256_update()).

Ideally, if only a single digest is enabled - say SHA-256 - then calling
mbedtls_md_update() should _directly_ jump to mbedtls_sha256_update(),
with both layers of indirection removed. So far, however, setting
MBEDTLS_MD_SINGLE_HASH will only remove the second - function pointer -
layer of indirection, while keeping the non-inlined stub implementations
of e.g. mbedtls_md_update() around.

This commit is a step towards allowing to define implementations of
the MD API as `static inline` in case we know that they are so small
that they should be defined in md.h and not in md.c.

In a nutshell, the approach is as follows: For an MD API function
mbedtls_md_xxx() that should be inlin-able, introduce its implementation
as a `static inline` wrapper `mbedtls_md_xxx_internal()` in md.h,
and then define mbedtls_md_xxx() either in md.h or in md.c, by just
calling mbedtls_md_xxx_internal().

Moving the implementations of those MD API functions that should be
inlinable to md.h requires the presence of both the MD info struct
and all specific digest wrapper functions in md.h, and this is what
this commit ensures, by moving them from md.c into a new internal
header file md_internal.h. Implementing the aforementioned wrappers for
those MD API that should be inlinable is left for subsequent commits.
diff --git a/library/md.c b/library/md.c
index 8d8f337..f81a1a9 100644
--- a/library/md.c
+++ b/library/md.c
@@ -48,166 +48,7 @@
 #include <stdio.h>
 #endif
 
-#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
-
-/*
- * Message-digest information macro definition
- */
-
-/* SHA-256 */
-#define MBEDTLS_MD_INFO_SHA256_TYPE         MBEDTLS_MD_SHA256
-#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  sha256_starts_wrap
-#define MBEDTLS_MD_INFO_SHA256_UPDATE_FUNC  sha224_update_wrap
-#define MBEDTLS_MD_INFO_SHA256_FINISH_FUNC  sha224_finish_wrap
-#define MBEDTLS_MD_INFO_SHA256_DIGEST_FUNC  sha256_wrap
-#define MBEDTLS_MD_INFO_SHA256_ALLOC_FUNC   sha224_ctx_alloc
-#define MBEDTLS_MD_INFO_SHA256_FREE_FUNC    sha224_ctx_free
-#define MBEDTLS_MD_INFO_SHA256_CLONE_FUNC   sha224_clone_wrap
-#define MBEDTLS_MD_INFO_SHA256_PROCESS_FUNC sha224_process_wrap
-
-/*
- * Helper macros to extract fields from ciphersuites.
- */
-
-#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_XXX_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_XXX( MBEDTLS_MD_SINGLE_HASH ).
- * where MBEDTLS_MD_SINGLE_HASH expands to MBEDTLS_MD_INFO_XXX. */
-#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 */
-    mbedtls_md_type_t type;
-
-    /** Name of the message digest */
-    const char * name;
-
-    /** Output length of the digest function in bytes */
-    int size;
-
-    /** Block length of the digest function in bytes */
-    int block_size;
-
-    /** Digest initialisation function */
-    mbedtls_md_starts_func_t *starts_func;
-
-    /** Digest update function */
-    mbedtls_md_update_func_t *update_func;
-
-    /** Digest finalisation function */
-    mbedtls_md_finish_func_t *finish_func;
-
-    /** Generic digest function */
-    mbedtls_md_digest_func_t *digest_func;
-
-    /** Allocate a new context */
-    mbedtls_md_ctx_alloc_func_t *ctx_alloc_func;
-
-    /** Free the given context */
-    mbedtls_md_ctx_free_func_t *ctx_free_func;
-
-    /** Clone state from a context */
-    mbedtls_md_clone_func_t *clone_func;
-
-    /** Internal use only */
-    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.
@@ -217,71 +58,21 @@
 /*
  * MD-2
  */
-
 #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 ) );
-}
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
 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_starts_wrap,
+    mbedtls_md2_update_wrap,
+    mbedtls_md2_finish_wrap,
     mbedtls_md2_ret,
-    md2_ctx_alloc,
-    md2_ctx_free,
-    md2_clone_wrap,
-    md2_process_wrap,
+    mbedtls_md2_ctx_alloc,
+    mbedtls_md2_ctx_free,
+    mbedtls_md2_clone_wrap,
+    mbedtls_md2_process_wrap,
 };
-#endif /* !MBEDTLS_MD_SINGLE_HASH */
-
 #endif /* MBEDTLS_MD2_C */
 
 /*
@@ -289,67 +80,20 @@
  */
 
 #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 ) );
-}
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
 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_starts_wrap,
+    mbedtls_md4_update_wrap,
+    mbedtls_md4_finish_wrap,
     mbedtls_md4_ret,
-    md4_ctx_alloc,
-    md4_ctx_free,
-    md4_clone_wrap,
-    md4_process_wrap,
+    mbedtls_md4_ctx_alloc,
+    mbedtls_md4_ctx_free,
+    mbedtls_md4_clone_wrap,
+    mbedtls_md4_process_wrap,
 };
-#endif /* MBEDTLS_MD_SINGLE_HASH */
-
 #endif /* MBEDTLS_MD4_C */
 
 /*
@@ -357,67 +101,20 @@
  */
 
 #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 ) );
-}
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
 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_starts_wrap,
+    mbedtls_md5_update_wrap,
+    mbedtls_md5_finish_wrap,
     mbedtls_md5_ret,
-    md5_ctx_alloc,
-    md5_ctx_free,
-    md5_clone_wrap,
-    md5_process_wrap,
+    mbedtls_md5_ctx_alloc,
+    mbedtls_md5_ctx_free,
+    mbedtls_md5_clone_wrap,
+    mbedtls_md5_process_wrap,
 };
-#endif /* MBEDTLS_MD_SINGLE_HASH */
-
 #endif /* MBEDTLS_MD5_C */
 
 /*
@@ -425,70 +122,20 @@
  */
 
 #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 ) );
-}
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
 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_starts_wrap,
+    mbedtls_ripemd160_update_wrap,
+    mbedtls_ripemd160_finish_wrap,
     mbedtls_ripemd160_ret,
-    ripemd160_ctx_alloc,
-    ripemd160_ctx_free,
-    ripemd160_clone_wrap,
-    ripemd160_process_wrap,
+    mbedtls_ripemd160_ctx_alloc,
+    mbedtls_ripemd160_ctx_free,
+    mbedtls_ripemd160_clone_wrap,
+    mbedtls_ripemd160_process_wrap,
 };
-#endif /* !MBEDTLS_MD_SINGLE_HASH */
-
 #endif /* MBEDTLS_RIPEMD160_C */
 
 /*
@@ -496,69 +143,20 @@
  */
 
 #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 ) );
-}
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
 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_starts_wrap,
+    mbedtls_sha1_update_wrap,
+    mbedtls_sha1_finish_wrap,
     mbedtls_sha1_ret,
-    sha1_ctx_alloc,
-    sha1_ctx_free,
-    sha1_clone_wrap,
-    sha1_process_wrap,
+    mbedtls_sha1_ctx_alloc,
+    mbedtls_sha1_ctx_free,
+    mbedtls_sha1_clone_wrap,
+    mbedtls_sha1_process_wrap,
 };
-#endif /* !MBEDTLS_MD_SINGLE_HASH */
-
 #endif /* MBEDTLS_SHA1_C */
 
 /*
@@ -566,98 +164,24 @@
  */
 
 #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_MD_SINGLE_HASH)
 #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,
+    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 */
-#endif /* !MBEDTLS_MD_SINGLE_HASH */
-
-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 ) );
-}
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
 const mbedtls_md_info_t mbedtls_sha256_info =
     MBEDTLS_MD_INFO( MBEDTLS_MD_INFO_SHA256 );
-#endif /* !MBEDTLS_MD_SINGLE_HASH */
-
 #endif /* MBEDTLS_SHA256_C */
 
 /*
@@ -665,307 +189,37 @@
  */
 
 #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 ) );
-}
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
 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,
+    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,
 };
-#endif /* MBEDTLS_MD_SINGLE_HASH */
-
-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 ) );
-}
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
 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,
+    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_MD_SINGLE_HASH */
-
 #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 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 */
-
-#if !defined(MBEDTLS_MD_SINGLE_HASH)
-
-/*
  * Reminder: update profiles in x509_crt.c when adding a new hash!
  */
 static const int supported_digests[] = {