From 40ce79f1e6c57ba6e9c5fe5ea54c37d361f719a6 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 15 Sep 2013 17:43:54 +0200 Subject: [PATCH] Moved DHM parsing from X509 module to DHM module --- include/polarssl/dhm.h | 31 +++++ include/polarssl/error.h | 2 +- include/polarssl/x509.h | 25 ---- library/dhm.c | 187 ++++++++++++++++++++++++++- library/error.c | 6 + library/x509parse.c | 129 +----------------- programs/test/selftest.c | 6 + tests/suites/test_suite_dhm.data | 3 + tests/suites/test_suite_dhm.function | 7 + 9 files changed, 241 insertions(+), 155 deletions(-) diff --git a/include/polarssl/dhm.h b/include/polarssl/dhm.h index 09de70b0e..0152dc9fe 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 @@ int dhm_calc_secret( dhm_context *ctx, */ 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 8279df5b4..205a105a9 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 3b5395a71..2fa00f6c6 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -472,31 +472,6 @@ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ); #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 f43b047c3..98c8e9f86 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 +#define polarssl_malloc malloc +#define polarssl_free free +#endif + /* * helper to validate the mpi size and import it */ @@ -372,14 +388,183 @@ void dhm_free( dhm_context *ctx ) 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 b0e3ebd20..78c5faa56 100644 --- a/library/error.c +++ b/library/error.c @@ -206,6 +206,12 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) 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 de4ed7f7d..5d32167f3 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2219,113 +2219,6 @@ int x509parse_public_key_rsa( rsa_context *rsa, } #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 @@ -3418,9 +3311,6 @@ int x509_self_test( int verbose ) 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 @@ int x509_self_test( int verbose ) 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 02606fab0..5b8706ba2 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 @@ int main( int argc, char *argv[] ) 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 168c77c1b..aecbfc5c9 100644 --- a/tests/suites/test_suite_dhm.data +++ b/tests/suites/test_suite_dhm.data @@ -6,3 +6,6 @@ dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622" 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 e8d9cea84..dcf236312 100644 --- a/tests/suites/test_suite_dhm.function +++ b/tests/suites/test_suite_dhm.function @@ -93,3 +93,10 @@ void dhm_do_dhm( int radix_P, char *input_P, dhm_free( &ctx_cli ); } /* END_CASE */ + +/* BEGIN_CASE */ +void dhm_selftest() +{ + TEST_ASSERT( dhm_self_test( 0 ) == 0 ); +} +/* END_CASE */