Implement md_file in the MD layer
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index 3164788..cb3e058 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -247,6 +247,7 @@
 int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
         unsigned char *output );
 
+#if defined(MBEDTLS_FS_IO)
 /**
  * \brief          Output = message_digest( file contents )
  *
@@ -259,7 +260,8 @@
  *                 MBEDTLS_ERR_MD_BAD_INPUT_DATA if md_info was NULL.
  */
 int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path,
-             unsigned char *output );
+                     unsigned char *output );
+#endif /* MBEDTLS_FS_IO */
 
 /**
  * \brief           Set HMAC key and prepare to authenticate a new message.
diff --git a/include/mbedtls/md_internal.h b/include/mbedtls/md_internal.h
index d42dc5c..8cc8c5b 100644
--- a/include/mbedtls/md_internal.h
+++ b/include/mbedtls/md_internal.h
@@ -71,9 +71,6 @@
     void (*digest_func)( const unsigned char *input, size_t ilen,
                          unsigned char *output );
 
-    /** Generic file digest function */
-    int (*file_func)( const char *path, unsigned char *output );
-
     /** Allocate a new context */
     void * (*ctx_alloc_func)( void );
 
diff --git a/library/md.c b/library/md.c
index dfa4526..737059a 100644
--- a/library/md.c
+++ b/library/md.c
@@ -45,9 +45,8 @@
 
 #include <string.h>
 
-#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
-    !defined(EFI32)
-#define strcasecmp  _stricmp
+#if defined(MBEDTLS_FS_IO)
+#include <stdio.h>
 #endif
 
 /* Implementation that should never be optimized out by the compiler */
@@ -270,28 +269,49 @@
     return( 0 );
 }
 
+#if defined(MBEDTLS_FS_IO)
 int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output )
 {
-#if defined(MBEDTLS_FS_IO)
     int ret;
-#endif
+    FILE *f;
+    size_t n;
+    mbedtls_md_context_t ctx;
+    unsigned char buf[1024];
 
     if( md_info == NULL )
         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
 
-#if defined(MBEDTLS_FS_IO)
-    ret = md_info->file_func( path, output );
-    if( ret != 0 )
-        return( MBEDTLS_ERR_MD_FILE_IO_ERROR + ret );
+    mbedtls_md_init( &ctx );
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+    {
+        ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;
+        goto cleanup;
+    }
+
+    if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
+        goto cleanup;
+
+    md_info->starts_func( ctx.md_ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        md_info->update_func( ctx.md_ctx, buf, n );
+
+    if( ferror( f ) != 0 )
+    {
+        ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;
+        goto cleanup;
+    }
+
+    md_info->finish_func( ctx.md_ctx, output );
+
+cleanup:
+    fclose( f );
+    mbedtls_md_free( &ctx );
 
     return( ret );
-#else
-    ((void) path);
-    ((void) output);
-
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif /* MBEDTLS_FS_IO */
 }
+#endif /* MBEDTLS_FS_IO */
 
 int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen )
 {
diff --git a/library/md_wrap.c b/library/md_wrap.c
index 4f12ed6..c1140d7 100644
--- a/library/md_wrap.c
+++ b/library/md_wrap.c
@@ -93,17 +93,6 @@
     mbedtls_md2_finish( (mbedtls_md2_context *) ctx, output );
 }
 
-static int md2_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_md2_file( path, output );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void * md2_ctx_alloc( void )
 {
     return mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) );
@@ -131,7 +120,6 @@
     md2_update_wrap,
     md2_finish_wrap,
     mbedtls_md2,
-    md2_file_wrap,
     md2_ctx_alloc,
     md2_ctx_free,
     md2_process_wrap,
@@ -157,17 +145,6 @@
     mbedtls_md4_finish( (mbedtls_md4_context *) ctx, output );
 }
 
-static int md4_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_md4_file( path, output );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void *md4_ctx_alloc( void )
 {
     return mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) );
@@ -193,7 +170,6 @@
     md4_update_wrap,
     md4_finish_wrap,
     mbedtls_md4,
-    md4_file_wrap,
     md4_ctx_alloc,
     md4_ctx_free,
     md4_process_wrap,
@@ -219,17 +195,6 @@
     mbedtls_md5_finish( (mbedtls_md5_context *) ctx, output );
 }
 
-static int md5_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_md5_file( path, output );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void * md5_ctx_alloc( void )
 {
     return mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) );
@@ -255,7 +220,6 @@
     md5_update_wrap,
     md5_finish_wrap,
     mbedtls_md5,
-    md5_file_wrap,
     md5_ctx_alloc,
     md5_ctx_free,
     md5_process_wrap,
@@ -281,17 +245,6 @@
     mbedtls_ripemd160_finish( (mbedtls_ripemd160_context *) ctx, output );
 }
 
-static int ripemd160_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_ripemd160_file( path, output );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void * ripemd160_ctx_alloc( void )
 {
     mbedtls_ripemd160_context *ctx;
@@ -325,7 +278,6 @@
     ripemd160_update_wrap,
     ripemd160_finish_wrap,
     mbedtls_ripemd160,
-    ripemd160_file_wrap,
     ripemd160_ctx_alloc,
     ripemd160_ctx_free,
     ripemd160_process_wrap,
@@ -351,17 +303,6 @@
     mbedtls_sha1_finish( (mbedtls_sha1_context *) ctx, output );
 }
 
-static int sha1_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_sha1_file( path, output );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void * sha1_ctx_alloc( void )
 {
     mbedtls_sha1_context *ctx;
@@ -395,7 +336,6 @@
     sha1_update_wrap,
     sha1_finish_wrap,
     mbedtls_sha1,
-    sha1_file_wrap,
     sha1_ctx_alloc,
     sha1_ctx_free,
     sha1_process_wrap,
@@ -430,17 +370,6 @@
     mbedtls_sha256( input, ilen, output, 1 );
 }
 
-static int sha224_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_sha256_file( path, output, 1 );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void * sha224_ctx_alloc( void )
 {
     return mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) );
@@ -466,7 +395,6 @@
     sha224_update_wrap,
     sha224_finish_wrap,
     sha224_wrap,
-    sha224_file_wrap,
     sha224_ctx_alloc,
     sha224_ctx_free,
     sha224_process_wrap,
@@ -494,17 +422,6 @@
     mbedtls_sha256( input, ilen, output, 0 );
 }
 
-static int sha256_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_sha256_file( path, output, 0 );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void * sha256_ctx_alloc( void )
 {
     mbedtls_sha256_context *ctx;
@@ -538,7 +455,6 @@
     sha256_update_wrap,
     sha256_finish_wrap,
     sha256_wrap,
-    sha256_file_wrap,
     sha256_ctx_alloc,
     sha256_ctx_free,
     sha256_process_wrap,
@@ -570,17 +486,6 @@
     mbedtls_sha512( input, ilen, output, 1 );
 }
 
-static int sha384_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_sha512_file( path, output, 1 );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void * sha384_ctx_alloc( void )
 {
     return mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) );
@@ -606,7 +511,6 @@
     sha384_update_wrap,
     sha384_finish_wrap,
     sha384_wrap,
-    sha384_file_wrap,
     sha384_ctx_alloc,
     sha384_ctx_free,
     sha384_process_wrap,
@@ -634,17 +538,6 @@
     mbedtls_sha512( input, ilen, output, 0 );
 }
 
-static int sha512_file_wrap( const char *path, unsigned char *output )
-{
-#if defined(MBEDTLS_FS_IO)
-    return mbedtls_sha512_file( path, output, 0 );
-#else
-    ((void) path);
-    ((void) output);
-    return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
-#endif
-}
-
 static void * sha512_ctx_alloc( void )
 {
     mbedtls_sha512_context *ctx;
@@ -678,7 +571,6 @@
     sha512_update_wrap,
     sha512_finish_wrap,
     sha512_wrap,
-    sha512_file_wrap,
     sha512_ctx_alloc,
     sha512_ctx_free,
     sha512_process_wrap,
diff --git a/tests/suites/test_suite_md.function b/tests/suites/test_suite_md.function
index a3b87f7..099d109 100644
--- a/tests/suites/test_suite_md.function
+++ b/tests/suites/test_suite_md.function
@@ -68,7 +68,9 @@
 
     TEST_ASSERT( mbedtls_md( NULL, 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 );
+#endif
 
     TEST_ASSERT( mbedtls_md_hmac_starts( NULL, buf, 1 )
                  == MBEDTLS_ERR_MD_BAD_INPUT_DATA );