From 1b57b067518793957b552a7c8ffab534f860fe89 Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Thu, 6 Jan 2011 15:48:19 +0000
Subject: [PATCH] - Added reading of DHM context from memory and file
---
ChangeLog | 1 +
include/polarssl/certs.h | 1 +
include/polarssl/md.h | 2 +
include/polarssl/ssl.h | 11 ++++
include/polarssl/x509.h | 29 ++++++++-
library/certs.c | 7 +++
library/ssl_tls.c | 19 ++++++
library/x509parse.c | 133 +++++++++++++++++++++++++++++++++++++++
8 files changed, 201 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 4ac9de162..b19bd6c2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,7 @@ Features
with OpenVPN (donated by Fox-IT)
* Added generic cipher wrapper for integration
with OpenVPN (donated by Fox-IT)
+ * Added reading of DHM context from memory and file
= Version 0.14.0 released on 2010-08-16
Features
diff --git a/include/polarssl/certs.h b/include/polarssl/certs.h
index c79393233..af8fcd677 100644
--- a/include/polarssl/certs.h
+++ b/include/polarssl/certs.h
@@ -38,6 +38,7 @@ extern const char test_srv_crt[];
extern const char test_srv_key[];
extern const char test_cli_crt[];
extern const char test_cli_key[];
+extern const char test_dhm_params[];
#ifdef __cplusplus
}
diff --git a/include/polarssl/md.h b/include/polarssl/md.h
index b23167b2b..13250dd8f 100644
--- a/include/polarssl/md.h
+++ b/include/polarssl/md.h
@@ -41,6 +41,8 @@ typedef enum {
POLARSSL_MD_SHA512,
} md_type_t;
+#define POLARSSL_MD_MAX_SIZE 64 /* longest known is SHA512 */
+
/**
* Message digest information. Allows message digest functions to be called
* in a generic way.
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 100c00480..715a4e886 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -453,6 +453,17 @@ void ssl_set_own_cert( ssl_context *ssl, x509_cert *own_cert,
*/
int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G );
+/**
+ * \brief Set the Diffie-Hellman public P and G values,
+ * read from existing context (server-side only)
+ *
+ * \param ssl SSL context
+ * \param dhm_ctx Diffie-Hellman-Merkle context
+ *
+ * \return 0 if successful
+ */
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
+
/**
* \brief Set hostname for ServerName TLS Extension
*
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index cbcb5b09e..0df84332f 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -28,6 +28,7 @@
#define POLARSSL_X509_H
#include "polarssl/rsa.h"
+#include "polarssl/dhm.h"
/**
* @addtogroup x509_module
@@ -322,7 +323,7 @@ extern "C" {
#endif
/**
- * @name Functions to read in a certificate, CRL or private RSA key
+ * @name Functions to read in DHM parameters, a certificate, CRL or private RSA key
* @{
*/
@@ -404,7 +405,31 @@ int x509parse_key( rsa_context *rsa,
*/
int x509parse_keyfile( rsa_context *rsa, const char *path,
const char *password );
-/** @} name Functions to read in a certificate, CRL or private RSA key */
+
+/** @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 error code
+ */
+int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, int dhminlen );
+
+/** @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 error code
+ */
+int x509parse_dhmfile( dhm_context *rsa, const char *path );
+
+/** @} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */
diff --git a/library/certs.c b/library/certs.c
index 37de8c239..9df2eb250 100644
--- a/library/certs.c
+++ b/library/certs.c
@@ -186,4 +186,11 @@ const char test_cli_key[] =
"3vMGjy6jnBSaKoktW8ikY+4FHq+t5z63UN3RF367Iz0dWzIVocbxAQ==\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
+const char test_dhm_params[] =
+"-----BEGIN DH PARAMETERS-----\r\n"
+"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
+"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
+"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
+"-----END DH PARAMETERS-----\r\n";
+
#endif
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 67eff4728..11d50ac99 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1806,6 +1806,25 @@ int ssl_set_dh_param( ssl_context *ssl, const char *dhm_P, const char *dhm_G )
return( 0 );
}
+int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx )
+{
+ int ret;
+
+ if( ( ret = mpi_copy(&ssl->dhm_ctx.P, &dhm_ctx->P) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_copy", ret );
+ return( ret );
+ }
+
+ if( ( ret = mpi_copy(&ssl->dhm_ctx.G, &dhm_ctx->G) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "mpi_copy", ret );
+ return( ret );
+ }
+
+ return( 0 );
+}
+
int ssl_set_hostname( ssl_context *ssl, const char *hostname )
{
if( hostname == NULL )
diff --git a/library/x509parse.c b/library/x509parse.c
index ea9748c9f..e48ed949a 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
#include
@@ -1819,6 +1820,122 @@ int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
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
@@ -2511,6 +2628,7 @@ int x509_self_test( int verbose )
x509_cert cacert;
x509_cert clicert;
rsa_context rsa;
+ dhm_context dhm;
if( verbose != 0 )
printf( " X.509 certificate load: " );
@@ -2567,12 +2685,27 @@ int x509_self_test( int verbose )
return( ret );
}
+ 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