Make md_info_t an opaque structure

- more freedom for us to change it in the future
- enforces hygiene
- performance impact of making accessors no longer inline should really be
  negligible
diff --git a/ChangeLog b/ChangeLog
index b0900d2..ac04f82 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,7 @@
   * Support for DTLS 1.0 and 1.2 (RFC 6347).
 
 API Changes
+   * Change md_info_t into an opaque structure (use md_get_xxx() accessors).
    * Some constness fixes
    * Signature of mpi_mul_mpi() changed to make the last argument unsigned
    * Remove the PBKDF2 module (use PKCS5).
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index a1d6873..6728d8d 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -5,7 +5,7 @@
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  *
  *  This file is part of mbed TLS (https://tls.mbed.org)
  *
@@ -65,63 +65,9 @@
 #endif
 
 /**
- * Message digest information. Allows message digest functions to be called
- * in a generic way.
+ * Opaque struct defined in md_wrap.h
  */
-typedef struct {
-    /** Digest identifier */
-    md_type_t type;
-
-    /** Name of the message digest */
-    const char * name;
-
-    /** Output length of the digest function */
-    int size;
-
-    /** Digest initialisation function */
-    void (*starts_func)( void *ctx );
-
-    /** Digest update function */
-    void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
-
-    /** Digest finalisation function */
-    void (*finish_func)( void *ctx, unsigned char *output );
-
-    /** Generic digest function */
-    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 );
-
-    /** HMAC Initialisation function */
-    void (*hmac_starts_func)( void *ctx, const unsigned char *key,
-                              size_t keylen );
-
-    /** HMAC update function */
-    void (*hmac_update_func)( void *ctx, const unsigned char *input,
-                              size_t ilen );
-
-    /** HMAC finalisation function */
-    void (*hmac_finish_func)( void *ctx, unsigned char *output);
-
-    /** HMAC context reset function */
-    void (*hmac_reset_func)( void *ctx );
-
-    /** Generic HMAC function */
-    void (*hmac_func)( const unsigned char *key, size_t keylen,
-                       const unsigned char *input, size_t ilen,
-                       unsigned char *output );
-
-    /** Allocate a new context */
-    void * (*ctx_alloc_func)( void );
-
-    /** Free the given context */
-    void (*ctx_free_func)( void *ctx );
-
-    /** Internal use only */
-    void (*process_func)( void *ctx, const unsigned char *input );
-} md_info_t;
+typedef struct _md_info_t md_info_t;
 
 /**
  * Generic message digest context.
@@ -191,7 +137,7 @@
  *
  * \param ctx      context to initialise. May not be NULL. The
  *                 digest-specific context (ctx->md_ctx) must be NULL. It will
- *                 be allocated, and must be freed using md_free_ctx() later.
+ *                 be allocated, and must be freed using md_free() later.
  * \param md_info  message digest to use.
  *
  * \returns        \c 0 on success, \c POLARSSL_ERR_MD_BAD_INPUT_DATA on
@@ -207,13 +153,7 @@
  *
  * \return          size of the message digest output.
  */
-static inline unsigned char md_get_size( const md_info_t *md_info )
-{
-    if( md_info == NULL )
-        return( 0 );
-
-    return md_info->size;
-}
+unsigned char md_get_size( const md_info_t *md_info );
 
 /**
  * \brief           Returns the type of the message digest output.
@@ -222,13 +162,7 @@
  *
  * \return          type of the message digest output.
  */
-static inline md_type_t md_get_type( const md_info_t *md_info )
-{
-    if( md_info == NULL )
-        return( POLARSSL_MD_NONE );
-
-    return md_info->type;
-}
+md_type_t md_get_type( const md_info_t *md_info );
 
 /**
  * \brief           Returns the name of the message digest output.
@@ -237,13 +171,7 @@
  *
  * \return          name of the message digest output.
  */
-static inline const char *md_get_name( const md_info_t *md_info )
-{
-    if( md_info == NULL )
-        return( NULL );
-
-    return md_info->name;
-}
+const char *md_get_name( const md_info_t *md_info );
 
 /**
  * \brief          Set-up the given context for a new message digest
diff --git a/include/mbedtls/md_wrap.h b/include/mbedtls/md_wrap.h
index dd5fd6c..6fe377e 100644
--- a/include/mbedtls/md_wrap.h
+++ b/include/mbedtls/md_wrap.h
@@ -3,9 +3,11 @@
  *
  * \brief Message digest wrappers.
  *
+ * \warning This in an internal header. Do not include directly.
+ *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
- *  Copyright (C) 2006-2011, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  *
  *  This file is part of mbed TLS (https://tls.mbed.org)
  *
@@ -38,6 +40,65 @@
 extern "C" {
 #endif
 
+/**
+ * Message digest information.
+ * Allows message digest functions to be called in a generic way.
+ */
+struct _md_info_t {
+    /** Digest identifier */
+    md_type_t type;
+
+    /** Name of the message digest */
+    const char * name;
+
+    /** Output length of the digest function */
+    int size;
+
+    /** Digest initialisation function */
+    void (*starts_func)( void *ctx );
+
+    /** Digest update function */
+    void (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
+
+    /** Digest finalisation function */
+    void (*finish_func)( void *ctx, unsigned char *output );
+
+    /** Generic digest function */
+    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 );
+
+    /** HMAC Initialisation function */
+    void (*hmac_starts_func)( void *ctx, const unsigned char *key,
+                              size_t keylen );
+
+    /** HMAC update function */
+    void (*hmac_update_func)( void *ctx, const unsigned char *input,
+                              size_t ilen );
+
+    /** HMAC finalisation function */
+    void (*hmac_finish_func)( void *ctx, unsigned char *output);
+
+    /** HMAC context reset function */
+    void (*hmac_reset_func)( void *ctx );
+
+    /** Generic HMAC function */
+    void (*hmac_func)( const unsigned char *key, size_t keylen,
+                       const unsigned char *input, size_t ilen,
+                       unsigned char *output );
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)( void );
+
+    /** Free the given context */
+    void (*ctx_free_func)( void *ctx );
+
+    /** Internal use only */
+    void (*process_func)( void *ctx, const unsigned char *input );
+};
+
 #if defined(POLARSSL_MD2_C)
 extern const md_info_t md2_info;
 #endif
diff --git a/library/ecdsa.c b/library/ecdsa.c
index c95f90b..c39c9c3 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -60,8 +60,9 @@
     for( md_alg = md_list(); *md_alg != 0; md_alg++ )
     {
         if( ( md_cur = md_info_from_type( (md_type_t) *md_alg ) ) == NULL ||
-            (size_t) md_cur->size < min_size ||
-            ( md_picked != NULL && md_cur->size > md_picked->size ) )
+            (size_t) md_get_size( md_cur ) < min_size ||
+            ( md_picked != NULL &&
+              md_get_size( md_cur ) > md_get_size( md_picked ) ) )
             continue;
 
         md_picked = md_cur;
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index dc26b0d..2e4b682 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -62,7 +62,7 @@
 void hmac_drbg_update( hmac_drbg_context *ctx,
                        const unsigned char *additional, size_t add_len )
 {
-    size_t md_len = ctx->md_ctx.md_info->size;
+    size_t md_len = md_get_size( ctx->md_ctx.md_info );
     unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
     unsigned char sep[1];
     unsigned char K[POLARSSL_MD_MAX_SIZE];
@@ -105,8 +105,8 @@
      * Use the V memory location, which is currently all 0, to initialize the
      * MD context with an all-zero key. Then set V to its initial value.
      */
-    md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
-    memset( ctx->V, 0x01, md_info->size );
+    md_hmac_starts( &ctx->md_ctx, ctx->V, md_get_size( md_info ) );
+    memset( ctx->V, 0x01, md_get_size( md_info ) );
 
     hmac_drbg_update( ctx, data, data_len );
 
@@ -165,7 +165,7 @@
                     size_t len )
 {
     int ret;
-    size_t entropy_len;
+    size_t entropy_len, md_size;
 
     memset( ctx, 0, sizeof( hmac_drbg_context ) );
 
@@ -174,13 +174,15 @@
     if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
         return( ret );
 
+    md_size = md_get_size( md_info );
+
     /*
      * Set initial working state.
      * Use the V memory location, which is currently all 0, to initialize the
      * MD context with an all-zero key. Then set V to its initial value.
      */
-    md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
-    memset( ctx->V, 0x01, md_info->size );
+    md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
+    memset( ctx->V, 0x01, md_size );
 
     ctx->f_entropy = f_entropy;
     ctx->p_entropy = p_entropy;
@@ -194,9 +196,9 @@
      *
      * (This also matches the sizes used in the NIST test vectors.)
      */
-    entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
-                  md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
-                                        32;  /* better (256+) -> 256 bits */
+    entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+                  md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+                                  32;  /* better (256+) -> 256 bits */
 
     /*
      * For initialisation, use more entropy to emulate a nonce
diff --git a/library/md.c b/library/md.c
index c34e121..d8f6a96 100644
--- a/library/md.c
+++ b/library/md.c
@@ -329,4 +329,28 @@
     return( 0 );
 }
 
+unsigned char md_get_size( const md_info_t *md_info )
+{
+    if( md_info == NULL )
+        return( 0 );
+
+    return md_info->size;
+}
+
+md_type_t md_get_type( const md_info_t *md_info )
+{
+    if( md_info == NULL )
+        return( POLARSSL_MD_NONE );
+
+    return md_info->type;
+}
+
+const char *md_get_name( const md_info_t *md_info )
+{
+    if( md_info == NULL )
+        return( NULL );
+
+    return md_info->name;
+}
+
 #endif /* POLARSSL_MD_C */
diff --git a/library/pk.c b/library/pk.c
index af4a302..f083b86 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -166,7 +166,7 @@
     if( ( md_info = md_info_from_type( md_alg ) ) == NULL )
         return( -1 );
 
-    *hash_len = md_info->size;
+    *hash_len = md_get_size( md_info );
     return( 0 );
 }
 
diff --git a/library/rsa.c b/library/rsa.c
index e915e4f..d3ab4ed 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -473,7 +473,7 @@
     memset( mask, 0, POLARSSL_MD_MAX_SIZE );
     memset( counter, 0, 4 );
 
-    hlen = md_ctx->md_info->size;
+    hlen = md_get_size( md_ctx->md_info );
 
     // Generate and apply dbMask
     //
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 2b94af8..4fe767b 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -2194,7 +2194,7 @@
         }
 
         SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
-                (unsigned int) ( md_info_from_type( md_alg ) )->size );
+            (unsigned int) ( md_get_size( md_info_from_type( md_alg ) ) ) );
 
         /*
          * Verify signature
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index ff2c44b..b7c0335 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -3085,7 +3085,7 @@
         }
 
         SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
-                (unsigned int) ( md_info_from_type( md_alg ) )->size );
+            (unsigned int) ( md_get_size( md_info_from_type( md_alg ) ) ) );
 
         /*
          * Make the signature
diff --git a/library/x509.c b/library/x509.c
index 174e32d..67359a5 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -845,8 +845,8 @@
         mgf_md_info = md_info_from_type( pss_opts->mgf1_hash_id );
 
         ret = polarssl_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
-                              md_info ? md_info->name : "???",
-                              mgf_md_info ? mgf_md_info->name : "???",
+                              md_info ? md_get_name( md_info ) : "???",
+                              mgf_md_info ? md_get_name( mgf_md_info ) : "???",
                               pss_opts->expected_salt_len );
         SAFE_SNPRINTF();
     }
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 8b93473..7d12bca 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1505,7 +1505,7 @@
         md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash );
 
         if( pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
-                           crl_list->sig_md, hash, md_info->size,
+                           crl_list->sig_md, hash, md_get_size( md_info ),
                            crl_list->sig.p, crl_list->sig.len ) != 0 )
         {
             flags |= BADCRL_NOT_TRUSTED;
@@ -1768,7 +1768,7 @@
         }
 
         if( pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk,
-                           child->sig_md, hash, md_info->size,
+                           child->sig_md, hash, md_get_size( md_info ),
                            child->sig.p, child->sig.len ) != 0 )
         {
             continue;
@@ -1864,7 +1864,7 @@
         md( md_info, child->tbs.p, child->tbs.len, hash );
 
         if( pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
-                           child->sig_md, hash, md_info->size,
+                           child->sig_md, hash, md_get_size( md_info ),
                            child->sig.p, child->sig.len ) != 0 )
         {
             *flags |= BADCERT_NOT_TRUSTED;