Moved DHM parsing from X509 module to DHM module
diff --git a/include/polarssl/dhm.h b/include/polarssl/dhm.h
index 09de70b..0152dc9 100644
--- a/include/polarssl/dhm.h
+++ b/include/polarssl/dhm.h
@@ -38,6 +38,9 @@
 #define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED                -0x3200  /**< Reading of the public values failed. */
 #define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED                -0x3280  /**< Making of the public value failed. */
 #define POLARSSL_ERR_DHM_CALC_SECRET_FAILED                -0x3300  /**< Calculation of the DHM secret failed. */
+#define POLARSSL_ERR_DHM_INVALID_FORMAT                    -0x3380  /**< The ASN.1 data is not formatted correctly. */
+#define POLARSSL_ERR_DHM_MALLOC_FAILED                     -0x3400  /**< Allocation of memory failed. */
+#define POLARSSL_ERR_DHM_FILE_IO_ERROR                     -0x3480  /**< Read/write of file failed. */
 
 /**
  * RFC 3526 defines a number of standardized Diffie-Hellman groups
@@ -245,6 +248,34 @@
  */
 void dhm_free( dhm_context *ctx );
 
+#if defined(POLARSSL_ASN1_PARSE_C)
+/** \ingroup x509_module */
+/**
+ * \brief          Parse DHM parameters
+ *
+ * \param dhm      DHM context to be initialized
+ * \param dhmin    input buffer
+ * \param dhminlen size of the buffer
+ *
+ * \return         0 if successful, or a specific DHM or PEM error code
+ */
+int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin,
+                   size_t dhminlen );
+
+#if defined(POLARSSL_FS_IO)
+/** \ingroup x509_module */
+/**
+ * \brief          Load and parse DHM parameters
+ *
+ * \param dhm      DHM context to be initialized
+ * \param path     filename to read the DHM Parameters from
+ *
+ * \return         0 if successful, or a specific DHM or PEM error code
+ */
+int dhm_parse_dhmfile( dhm_context *dhm, const char *path );
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_ASN1_PARSE_C */
+
 /**
  * \brief          Checkup routine
  *
diff --git a/include/polarssl/error.h b/include/polarssl/error.h
index 8279df5..205a105 100644
--- a/include/polarssl/error.h
+++ b/include/polarssl/error.h
@@ -78,7 +78,7 @@
  * PKCS#12   1   4 (Started from top)
  * X509      2   18
  * PK        2   13 (Started from top)
- * DHM       3   6
+ * DHM       3   9
  * PKCS5     3   4 (Started from top)
  * RSA       4   9
  * ECP       4   4 (Started from top)
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index 3b5395a..2fa00f6 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -472,31 +472,6 @@
 #endif /* POLARSSL_FS_IO */
 #endif /* POLARSSL_RSA_C */
 
-/** \ingroup x509_module */
-/**
- * \brief          Parse DHM parameters
- *
- * \param dhm      DHM context to be initialized
- * \param dhmin    input buffer
- * \param dhminlen size of the buffer
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen );
-
-#if defined(POLARSSL_FS_IO)
-/** \ingroup x509_module */
-/**
- * \brief          Load and parse DHM parameters
- *
- * \param dhm      DHM context to be initialized
- * \param path     filename to read the DHM Parameters from
- *
- * \return         0 if successful, or a specific X509 or PEM error code
- */
-int x509parse_dhmfile( dhm_context *dhm, const char *path );
-#endif /* POLARSSL_FS_IO */
-
 /** \} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */
 
 /**
diff --git a/library/dhm.c b/library/dhm.c
index f43b047..98c8e9f 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -34,6 +34,22 @@
 
 #include "polarssl/dhm.h"
 
+#if defined(POLARSSL_PEM_C)
+#include "polarssl/pem.h"
+#endif
+
+#if defined(POLARSSL_ASN1_PARSE_C)
+#include "polarssl/asn1.h"
+#endif
+
+#if defined(POLARSSL_MEMORY_C)
+#include "polarssl/memory.h"
+#else
+#include <stdlib.h>
+#define polarssl_malloc     malloc
+#define polarssl_free       free
+#endif
+
 /*
  * helper to validate the mpi size and import it
  */
@@ -372,14 +388,183 @@
     memset( ctx, 0, sizeof( dhm_context ) );
 }
 
+#if defined(POLARSSL_ASN1_PARSE_C)
+/*
+ * Parse DHM parameters
+ */
+int dhm_parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
+{
+    int ret;
+    size_t len;
+    unsigned char *p, *end;
+#if defined(POLARSSL_PEM_C)
+    pem_context pem;
+
+    pem_init( &pem );
+    memset( dhm, 0, sizeof( dhm_context ) );
+
+    ret = pem_read_buffer( &pem,
+                           "-----BEGIN DH PARAMETERS-----",
+                           "-----END DH PARAMETERS-----",
+                           dhmin, NULL, 0, &dhminlen );
+
+    if( ret == 0 )
+    {
+        /*
+         * Was PEM encoded
+         */
+        dhminlen = pem.buflen;
+    }
+    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+        goto exit;
+
+    p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
+#else
+    p = (unsigned char *) dhmin;
+#endif
+    end = p + dhminlen;
+
+    /*
+     *  DHParams ::= SEQUENCE {
+     *      prime            INTEGER,  -- P
+     *      generator        INTEGER,  -- g
+     *  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret;
+        goto exit;
+    }
+
+    end = p + len;
+
+    if( ( ret = asn1_get_mpi( &p, end, &dhm->P  ) ) != 0 ||
+        ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT + ret;
+        goto exit;
+    }
+
+    if( p != end )
+    {
+        ret = POLARSSL_ERR_DHM_INVALID_FORMAT +
+              POLARSSL_ERR_ASN1_LENGTH_MISMATCH;
+        goto exit;
+    }
+
+    ret = 0;
+
+exit:
+#if defined(POLARSSL_PEM_C)
+    pem_free( &pem );
+#endif
+    if( ret != 0 )
+        dhm_free( dhm );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ */
+static int load_file( const char *path, unsigned char **buf, size_t *n )
+{
+    FILE *f;
+    long size;
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    if( ( size = ftell( f ) ) == -1 )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+    }
+    fseek( f, 0, SEEK_SET );
+
+    *n = (size_t) size;
+
+    if( *n + 1 == 0 ||
+        ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
+    {
+        fclose( f );
+        return( POLARSSL_ERR_DHM_MALLOC_FAILED );
+    }
+
+    if( fread( *buf, 1, *n, f ) != *n )
+    {
+        fclose( f );
+        polarssl_free( *buf );
+        return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    (*buf)[*n] = '\0';
+
+    return( 0 );
+}
+
+/*
+ * Load and parse DHM parameters
+ */
+int dhm_parse_dhmfile( dhm_context *dhm, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
+        return( ret );
+
+    ret = dhm_parse_dhm( dhm, buf, n );
+
+    memset( buf, 0, n + 1 );
+    polarssl_free( buf );
+
+    return( ret );
+}
+#endif /* POLARSSL_FS_IO */
+#endif /* POLARSSL_ASN1_PARSE_C */
+
 #if defined(POLARSSL_SELF_TEST)
 
+#include "polarssl/certs.h"
+
 /*
  * Checkup routine
  */
 int dhm_self_test( int verbose )
 {
-    return( verbose++ );
+#if defined(POLARSSL_CERTS_C)
+    int ret;
+    dhm_context dhm;
+
+    if( verbose != 0 )
+        printf( "  DHM parameter load: " );
+
+    if( ( ret = dhm_parse_dhm( &dhm, (const unsigned char *) test_dhm_params,
+                               strlen( test_dhm_params ) ) ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( ret );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n\n" );
+
+    dhm_free( &dhm );
+
+    return( 0 );
+#else
+    ((void) verbose);
+    return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
+#endif
 }
 
 #endif
diff --git a/library/error.c b/library/error.c
index b0e3ebd..78c5faa 100644
--- a/library/error.c
+++ b/library/error.c
@@ -206,6 +206,12 @@
             snprintf( buf, buflen, "DHM - Making of the public value failed" );
         if( use_ret == -(POLARSSL_ERR_DHM_CALC_SECRET_FAILED) )
             snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_INVALID_FORMAT) )
+            snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" );
+        if( use_ret == -(POLARSSL_ERR_DHM_MALLOC_FAILED) )
+            snprintf( buf, buflen, "DHM - Allocation of memory failed" );
+        if( use_ret == -(POLARSSL_ERR_DHM_FILE_IO_ERROR) )
+            snprintf( buf, buflen, "DHM - Read/write of file failed" );
 #endif /* POLARSSL_DHM_C */
 
 #if defined(POLARSSL_ECP_C)
diff --git a/library/x509parse.c b/library/x509parse.c
index de4ed7f..5d32167 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -2219,113 +2219,6 @@
 }
 #endif /* POLARSSL_RSA_C */
 
-#if defined(POLARSSL_DHM_C)
-/*
- * Parse DHM parameters
- */
-int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen )
-{
-    int ret;
-    size_t len;
-    unsigned char *p, *end;
-#if defined(POLARSSL_PEM_C)
-    pem_context pem;
-
-    pem_init( &pem );
-
-    ret = pem_read_buffer( &pem, 
-                           "-----BEGIN DH PARAMETERS-----",
-                           "-----END DH PARAMETERS-----",
-                           dhmin, NULL, 0, &dhminlen );
-
-    if( ret == 0 )
-    {
-        /*
-         * Was PEM encoded
-         */
-        dhminlen = pem.buflen;
-    }
-    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-    {
-        pem_free( &pem );
-        return( ret );
-    }
-
-    p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
-#else
-    p = (unsigned char *) dhmin;
-#endif
-    end = p + dhminlen;
-
-    memset( dhm, 0, sizeof( dhm_context ) );
-
-    /*
-     *  DHParams ::= SEQUENCE {
-     *      prime            INTEGER,  -- P
-     *      generator        INTEGER,  -- g
-     *  }
-     */
-    if( ( ret = asn1_get_tag( &p, end, &len,
-            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    end = p + len;
-
-    if( ( ret = asn1_get_mpi( &p, end, &dhm->P  ) ) != 0 ||
-        ( ret = asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        dhm_free( dhm );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret );
-    }
-
-    if( p != end )
-    {
-#if defined(POLARSSL_PEM_C)
-        pem_free( &pem );
-#endif
-        dhm_free( dhm );
-        return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT +
-                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
-    }
-
-#if defined(POLARSSL_PEM_C)
-    pem_free( &pem );
-#endif
-
-    return( 0 );
-}
-
-#if defined(POLARSSL_FS_IO)
-/*
- * Load and parse DHM parameters
- */
-int x509parse_dhmfile( dhm_context *dhm, const char *path )
-{
-    int ret;
-    size_t n;
-    unsigned char *buf;
-
-    if ( ( ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
-
-    ret = x509parse_dhm( dhm, buf, n );
-
-    memset( buf, 0, n + 1 );
-    polarssl_free( buf );
-
-    return( ret );
-}
-#endif /* POLARSSL_FS_IO */
-#endif /* POLARSSL_DHM_C */
-
 #if defined _MSC_VER && !defined snprintf
 #include <stdarg.h>
 
@@ -3418,9 +3311,6 @@
     x509_cert cacert;
     x509_cert clicert;
     pk_context pkey;
-#if defined(POLARSSL_DHM_C)
-    dhm_context dhm;
-#endif
 
     if( verbose != 0 )
         printf( "  X.509 certificate load: " );
@@ -3483,29 +3373,12 @@
         return( ret );
     }
 
-#if defined(POLARSSL_DHM_C)
     if( verbose != 0 )
-        printf( "passed\n  X.509 DHM parameter load: " );
-
-    if( ( ret = x509parse_dhm( &dhm, (const unsigned char *) test_dhm_params,
-                                     strlen( test_dhm_params ) ) ) != 0 )
-    {
-        if( verbose != 0 )
-            printf( "failed\n" );
-
-        return( ret );
-    }
-
-    if( verbose != 0 )
-        printf( "passed\n\n" );
-#endif
+        printf( "passed\n\n");
 
     x509_free( &cacert  );
     x509_free( &clicert );
     pk_free( &pkey );
-#if defined(POLARSSL_DHM_C)
-    dhm_free( &dhm );
-#endif
 
     return( 0 );
 #else
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 02606fa..5b8706b 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -33,6 +33,7 @@
 #include "polarssl/config.h"
 
 #include "polarssl/ctr_drbg.h"
+#include "polarssl/dhm.h"
 #include "polarssl/gcm.h"
 #include "polarssl/md2.h"
 #include "polarssl/md4.h"
@@ -172,6 +173,11 @@
         return( ret );
 #endif
 
+#if defined(POLARSSL_DHM_C)
+    if( ( ret = dhm_self_test( v ) ) != 0 )
+        return( ret );
+#endif
+
 #else
     printf( " POLARSSL_SELF_TEST not defined.\n" );
 #endif
diff --git a/tests/suites/test_suite_dhm.data b/tests/suites/test_suite_dhm.data
index 168c77c..aecbfc5 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -6,3 +6,6 @@
 
 Diffie-Hellman full exchange #3
 dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
+
+Diffie-Hellman selftest
+dhm_selftest:
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index e8d9cea..dcf2363 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -93,3 +93,10 @@
     dhm_free( &ctx_cli );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void dhm_selftest()
+{
+    TEST_ASSERT( dhm_self_test( 0 ) == 0 );
+}
+/* END_CASE */