- Added reading of DHM context from memory and file

diff --git a/library/x509parse.c b/library/x509parse.c
index ea9748c..e48ed94 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -47,6 +47,7 @@
 #include "polarssl/sha1.h"
 #include "polarssl/sha2.h"
 #include "polarssl/sha4.h"
+#include "polarssl/dhm.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -1819,6 +1820,122 @@
     return( ret );
 }
 
+/*
+ * Parse DHM parameters
+ */
+int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, int dhminlen )
+{
+    int ret, len;
+    unsigned char *buf, *s1, *s2;
+    unsigned char *p, *end;
+
+    s1 = (unsigned char *) strstr( (char *) dhmin,
+        "-----BEGIN DH PARAMETERS-----" );
+
+    if( s1 != NULL )
+    {
+        s2 = (unsigned char *) strstr( (char *) dhmin,
+            "-----END DH PARAMETERS-----" );
+
+        if( s2 == NULL || s2 <= s1 )
+            return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
+
+        s1 += 29;
+        if( *s1 == '\r' ) s1++;
+        if( *s1 == '\n' ) s1++;
+            else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
+
+        len = 0;
+        ret = base64_decode( NULL, &len, s1, s2 - s1 );
+
+        if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
+            return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
+
+        if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
+            return( 1 );
+
+        if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
+        {
+            free( buf );
+            return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
+        }
+
+        dhminlen = len;
+    }
+    else
+    {
+        buf = NULL;
+    }
+
+    memset( dhm, 0, sizeof( dhm_context ) );
+
+    p = ( s1 != NULL ) ? buf : (unsigned char *) dhmin;
+    end = p + dhminlen;
+
+    /*
+     *  DHParams ::= SEQUENCE {
+     *      prime            INTEGER,  -- P
+     *      generator        INTEGER,  -- g
+     *  }
+     */
+    if( ( ret = asn1_get_tag( &p, end, &len,
+            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+    {
+        if( s1 != NULL )
+            free( buf );
+
+        dhm_free( dhm );
+        return( POLARSSL_ERR_X509_KEY_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( s1 != NULL )
+            free( buf );
+
+        dhm_free( dhm );
+        return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
+    }
+
+    if( p != end )
+    {
+        if( s1 != NULL )
+            free( buf );
+
+        dhm_free( dhm );
+        return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
+                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+    }
+
+    if( s1 != NULL )
+        free( buf );
+
+    return( 0 );
+}
+
+/*
+ * Load and parse a private RSA key
+ */
+int x509parse_dhmfile( dhm_context *dhm, const char *path )
+{
+    int ret;
+    size_t n;
+    unsigned char *buf;
+
+    if ( load_file( path, &buf, &n ) )
+        return( 1 );
+
+    ret = x509parse_dhm( dhm, buf, (int) n);
+
+    memset( buf, 0, n + 1 );
+    free( buf );
+
+    return( ret );
+}
+
 #if defined _MSC_VER && !defined snprintf
 #include <stdarg.h>
 
@@ -2511,6 +2628,7 @@
     x509_cert cacert;
     x509_cert clicert;
     rsa_context rsa;
+    dhm_context dhm;
 
     if( verbose != 0 )
         printf( "  X.509 certificate load: " );
@@ -2568,11 +2686,26 @@
     }
 
     if( verbose != 0 )
+        printf( "passed\n  X.509 DHM parameter load: " );
+
+    i = strlen( test_dhm_params );
+    j = strlen( test_ca_pwd );
+
+    if( ( ret = x509parse_dhm( &dhm, (unsigned char *) test_dhm_params, i ) ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( ret );
+    }
+
+    if( verbose != 0 )
         printf( "passed\n\n" );
 
     x509_free( &cacert  );
     x509_free( &clicert );
     rsa_free( &rsa );
+    dhm_free( &dhm );
 
     return( 0 );
 #else