Add mbedtls_md_clone()
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index ad62739..9465a5a 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -164,6 +164,23 @@
 int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac );
 
 /**
+ * \brief           Clone the state of an MD context
+ *
+ * \note            The two contexts must have been setup to the same type
+ *                  (cloning from SHA-256 to SHA-512 make no sense).
+ *
+ * \warning         Only clones the MD state, not the HMAC state! (for now)
+ *
+ * \param dst       The destination context
+ * \param src       The context to be cloned
+ *
+ * \return          \c 0 on success,
+ *                  \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure.
+ */
+int mbedtls_md_clone( mbedtls_md_context_t *dst,
+                      const mbedtls_md_context_t *src );
+
+/**
  * \brief           Returns the size of the message digest output.
  *
  * \param md_info   message digest info
diff --git a/include/mbedtls/md_internal.h b/include/mbedtls/md_internal.h
index fe0feb3..f2a0632 100644
--- a/include/mbedtls/md_internal.h
+++ b/include/mbedtls/md_internal.h
@@ -77,6 +77,9 @@
     /** Free the given context */
     void (*ctx_free_func)( void *ctx );
 
+    /** Clone state from a context */
+    void (*clone_func)( void *dst, const void *src );
+
     /** Internal use only */
     void (*process_func)( void *ctx, const unsigned char *input );
 };
diff --git a/library/md.c b/library/md.c
index 1220a87..a2c020b 100644
--- a/library/md.c
+++ b/library/md.c
@@ -201,6 +201,21 @@
     mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) );
 }
 
+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 )
+    {
+        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    }
+
+    dst->md_info->clone_func( 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 )
 {
diff --git a/library/md_wrap.c b/library/md_wrap.c
index c3adce3..b4a6f69 100644
--- a/library/md_wrap.c
+++ b/library/md_wrap.c
@@ -104,6 +104,12 @@
     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 void md2_process_wrap( void *ctx, const unsigned char *data )
 {
     ((void) data);
@@ -122,6 +128,7 @@
     mbedtls_md2,
     md2_ctx_alloc,
     md2_ctx_free,
+    md2_clone_wrap,
     md2_process_wrap,
 };
 
@@ -161,6 +168,12 @@
     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 void md4_process_wrap( void *ctx, const unsigned char *data )
 {
     mbedtls_md4_process( (mbedtls_md4_context *) ctx, data );
@@ -177,6 +190,7 @@
     mbedtls_md4,
     md4_ctx_alloc,
     md4_ctx_free,
+    md4_clone_wrap,
     md4_process_wrap,
 };
 
@@ -216,6 +230,12 @@
     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 void md5_process_wrap( void *ctx, const unsigned char *data )
 {
     mbedtls_md5_process( (mbedtls_md5_context *) ctx, data );
@@ -232,6 +252,7 @@
     mbedtls_md5,
     md5_ctx_alloc,
     md5_ctx_free,
+    md5_clone_wrap,
     md5_process_wrap,
 };
 
@@ -271,6 +292,12 @@
     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 void ripemd160_process_wrap( void *ctx, const unsigned char *data )
 {
     mbedtls_ripemd160_process( (mbedtls_ripemd160_context *) ctx, data );
@@ -287,6 +314,7 @@
     mbedtls_ripemd160,
     ripemd160_ctx_alloc,
     ripemd160_ctx_free,
+    ripemd160_clone_wrap,
     ripemd160_process_wrap,
 };
 
@@ -320,6 +348,12 @@
     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 );
@@ -342,6 +376,7 @@
     mbedtls_sha1,
     sha1_ctx_alloc,
     sha1_ctx_free,
+    sha1_clone_wrap,
     sha1_process_wrap,
 };
 
@@ -390,6 +425,12 @@
     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 void sha224_process_wrap( void *ctx, const unsigned char *data )
 {
     mbedtls_sha256_process( (mbedtls_sha256_context *) ctx, data );
@@ -406,6 +447,7 @@
     sha224_wrap,
     sha224_ctx_alloc,
     sha224_ctx_free,
+    sha224_clone_wrap,
     sha224_process_wrap,
 };
 
@@ -431,6 +473,7 @@
     sha256_wrap,
     sha224_ctx_alloc,
     sha224_ctx_free,
+    sha224_clone_wrap,
     sha224_process_wrap,
 };
 
@@ -476,6 +519,12 @@
     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 void sha384_process_wrap( void *ctx, const unsigned char *data )
 {
     mbedtls_sha512_process( (mbedtls_sha512_context *) ctx, data );
@@ -492,6 +541,7 @@
     sha384_wrap,
     sha384_ctx_alloc,
     sha384_ctx_free,
+    sha384_clone_wrap,
     sha384_process_wrap,
 };
 
@@ -517,6 +567,7 @@
     sha512_wrap,
     sha384_ctx_alloc,
     sha384_ctx_free,
+    sha384_clone_wrap,
     sha384_process_wrap,
 };