Commit 5ae8fbea authored by Sebastien Decugis's avatar Sebastien Decugis
Browse files

Allow TLS Diffie-Hellmann parameters to be loaded from a file (ticket #17)

parent 87b2e89b
......@@ -120,6 +120,13 @@ TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key
# 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
......
......@@ -133,7 +133,10 @@ void fd_conf_dump()
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 @@ int fd_conf_parse()
&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 @@ int fd_conf_parse()
/* 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 @@ int fd_conf_deinit()
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), );
......
......@@ -136,6 +136,7 @@ qstring \"[^\"\n]*\"
(?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 */
......
......@@ -117,6 +117,7 @@ struct peer_info fddpi;
%token TLS_CRL
%token TLS_PRIO
%token TLS_DH_BITS
%token TLS_DH_FILE
/* -------------------------------------- */
......@@ -581,12 +582,19 @@ tls_prio: TLS_PRIO '=' QSTRING ';'
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);
}
;
......@@ -111,6 +111,7 @@ struct fd_config {
char * prio_string;
unsigned int dh_bits;
char * dh_file;
/* GNUTLS parameters */
gnutls_priority_t prio_cache;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment