changeset 578:7c9a00bfd115

Allow TLS Diffie-Hellmann parameters to be loaded from a file (ticket #17)
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 27 Oct 2010 10:52:30 +0900
parents 9dae8bc2d04a
children 8c62a1c435e8
files doc/freediameter.conf.sample freeDiameter/config.c freeDiameter/fdd.l freeDiameter/fdd.y include/freeDiameter/freeDiameter.h
diffstat 5 files changed, 79 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/doc/freediameter.conf.sample	Wed Oct 20 15:37:49 2010 +0900
+++ b/doc/freediameter.conf.sample	Wed Oct 27 10:52:30 2010 +0900
@@ -120,6 +120,13 @@
 # Default : 1024
 #TLS_DH_Bits = 1024;
 
+# Alternatively, you can specify a file to load the PKCS#3 encoded
+# DH parameters directly from. This accelerates the daemon start 
+# but is slightly less secure. If this file is provided, the
+# TLS_DH_Bits parameters has no effect.
+# Default : no default.
+#TLS_DH_File = "<file.PEM>";
+
 
 ##############################################################
 ##  Timers configuration
--- a/freeDiameter/config.c	Wed Oct 20 15:37:49 2010 +0900
+++ b/freeDiameter/config.c	Wed Oct 27 10:52:30 2010 +0900
@@ -133,7 +133,10 @@
 	fd_log_debug("          - CA (trust) ... : %s (%d certs)\n", fd_g_config->cnf_sec_data.ca_file ?: "(none)", fd_g_config->cnf_sec_data.ca_file_nr);
 	fd_log_debug("          - CRL .......... : %s\n", fd_g_config->cnf_sec_data.crl_file ?: "(none)");
 	fd_log_debug("          - Priority ..... : %s\n", fd_g_config->cnf_sec_data.prio_string ?: "(default: '" GNUTLS_DEFAULT_PRIORITY "')");
-	fd_log_debug("          - DH bits ...... : %d\n", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS);
+	if (fd_g_config->cnf_sec_data.dh_file)
+		fd_log_debug("          - DH file ...... : %s\n", fd_g_config->cnf_sec_data.dh_file);
+	else
+		fd_log_debug("          - DH bits ...... : %d\n", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS);
 	
 	fd_log_debug("  Origin-State-Id ........ : %u\n", fd_g_config->cnf_orstateid);
 }
@@ -260,14 +263,6 @@
 					&err_pos),
 				 { TRACE_DEBUG(INFO, "Error in priority string at position : %s", err_pos); return EINVAL; } );
 	}
-	if (! fd_g_config->cnf_sec_data.dh_bits) {
-		TRACE_DEBUG(INFO, "Generating Diffie-Hellman parameters of size %d (this takes a few seconds)... ", GNUTLS_DEFAULT_DHBITS);
-		CHECK_GNUTLS_DO( gnutls_dh_params_generate2( 
-					fd_g_config->cnf_sec_data.dh_cache,
-					GNUTLS_DEFAULT_DHBITS),
-				 { TRACE_DEBUG(INFO, "Error in DH bits value : %d", GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
-	}
-	
 	
 	/* Verify that our certificate is valid -- otherwise remote peers will reject it */
 	{
@@ -402,6 +397,56 @@
 	
 	/* gnutls_certificate_set_verify_limits -- so far the default values are fine... */
 	
+	/* DH */
+	if (fd_g_config->cnf_sec_data.dh_file) {
+		gnutls_datum_t dhparams = { NULL, 0 };
+		size_t alloc = 0;
+		FILE *stream = fopen (fd_g_config->cnf_sec_data.dh_file, "rb");
+		if (!stream) {
+			int err = errno;
+			TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s\n", fd_g_config->cnf_sec_data.dh_file, strerror(err));
+			return err; 
+		}
+		do {
+			uint8_t * realloced = NULL;
+			size_t read = 0;
+			
+			if (alloc < dhparams.size + BUFSIZ + 1) {
+				alloc += alloc / 2 + BUFSIZ + 1;
+				CHECK_MALLOC_DO( realloced = realloc(dhparams.data, alloc),
+					{
+						free(dhparams.data);
+						return ENOMEM;
+					} )
+				dhparams.data = realloced;
+			}
+			
+			read = fread( dhparams.data + dhparams.size, 1, alloc - dhparams.size - 1, stream );
+			dhparams.size += read;
+			
+			if (ferror(stream)) {
+				int err = errno;
+				TRACE_DEBUG(INFO, "An error occurred while reading '%s': %s\n", fd_g_config->cnf_sec_data.dh_file, strerror(err));
+				return err; 
+			}
+		} while (!feof(stream));
+		dhparams.data[dhparams.size] = '\0';
+		fclose(stream);
+		CHECK_GNUTLS_DO( gnutls_dh_params_import_pkcs3( 
+					fd_g_config->cnf_sec_data.dh_cache,
+					&dhparams,
+					GNUTLS_X509_FMT_PEM),
+					 { TRACE_DEBUG(INFO, "Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
+		free(dhparams.data);
+		
+	} else {
+		TRACE_DEBUG(INFO, "Generating fresh Diffie-Hellman parameters of size %d (this takes some time)... ", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS);
+		CHECK_GNUTLS_DO( gnutls_dh_params_generate2( 
+					fd_g_config->cnf_sec_data.dh_cache,
+					fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS),
+					 { TRACE_DEBUG(INFO, "Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } );
+	}			
+	
 	return 0;
 }
 
@@ -421,6 +466,7 @@
 	free(fd_g_config->cnf_sec_data.ca_file); fd_g_config->cnf_sec_data.ca_file = NULL;
 	free(fd_g_config->cnf_sec_data.crl_file); fd_g_config->cnf_sec_data.crl_file = NULL;
 	free(fd_g_config->cnf_sec_data.prio_string); fd_g_config->cnf_sec_data.prio_string = NULL;
+	free(fd_g_config->cnf_sec_data.dh_file); fd_g_config->cnf_sec_data.dh_file = NULL;
 	
 	/* Destroy dictionary */
 	CHECK_FCT_DO( fd_dict_fini(&fd_g_config->cnf_dict), );
--- a/freeDiameter/fdd.l	Wed Oct 20 15:37:49 2010 +0900
+++ b/freeDiameter/fdd.l	Wed Oct 27 10:52:30 2010 +0900
@@ -136,6 +136,7 @@
 (?i:"TLS_CRL")		{ return TLS_CRL;	}
 (?i:"TLS_Prio")		{ return TLS_PRIO;	}
 (?i:"TLS_DH_bits")	{ return TLS_DH_BITS;	}
+(?i:"TLS_DH_file")	{ return TLS_DH_FILE;	}
 
 
 	/* Valid single characters for yyparse */
--- a/freeDiameter/fdd.y	Wed Oct 20 15:37:49 2010 +0900
+++ b/freeDiameter/fdd.y	Wed Oct 27 10:52:30 2010 +0900
@@ -117,6 +117,7 @@
 %token		TLS_CRL
 %token		TLS_PRIO
 %token		TLS_DH_BITS
+%token		TLS_DH_FILE
 
 
 /* -------------------------------------- */
@@ -581,12 +582,19 @@
 tls_dh:			TLS_DH_BITS '=' INTEGER ';'
 			{
 				conf->cnf_sec_data.dh_bits = $3;
-				TRACE_DEBUG(FULL, "Generating DH parameters...");
-				CHECK_GNUTLS_DO( gnutls_dh_params_generate2( 
-							conf->cnf_sec_data.dh_cache,
-							conf->cnf_sec_data.dh_bits),
-						{ yyerror (&yylloc, conf, "Error setting DH Bits parameters."); 
-						 YYERROR; } );
-				TRACE_DEBUG(FULL, "DH parameters generated.");
+			}
+			| TLS_DH_FILE '=' QSTRING ';'
+			{
+				FILE * fd;
+				free(conf->cnf_sec_data.dh_file);
+				conf->cnf_sec_data.dh_file = $3;
+				fd = fopen($3, "r");
+				if (fd == NULL) {
+					int ret = errno;
+					TRACE_DEBUG(INFO, "Unable to open DH file %s for reading: %s\n", $3, strerror(ret));
+					yyerror (&yylloc, conf, "Error on file name"); 
+					YYERROR;
+				}
+				fclose(fd);
 			}
 			;
--- a/include/freeDiameter/freeDiameter.h	Wed Oct 20 15:37:49 2010 +0900
+++ b/include/freeDiameter/freeDiameter.h	Wed Oct 27 10:52:30 2010 +0900
@@ -111,6 +111,7 @@
 		
 		char *				 prio_string;
 		unsigned int 			 dh_bits;
+		char *				 dh_file;
 		
 		/* GNUTLS parameters */
 		gnutls_priority_t 		 prio_cache;
"Welcome to our mercurial repository"