summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--lib/auth/anon.c2
-rw-r--r--lib/auth/dh_common.c18
-rw-r--r--lib/auth/dh_common.h3
-rw-r--r--lib/auth/dhe.c2
-rw-r--r--lib/auth/dhe_psk.c2
-rw-r--r--lib/crypto-backend.h1
-rw-r--r--lib/gnutls_dh.c13
-rw-r--r--lib/gnutls_dh.h3
-rw-r--r--lib/gnutls_dh_primes.c35
-rw-r--r--lib/gnutls_int.h2
-rw-r--r--lib/nettle/mpi.c9
-rw-r--r--src/benchmark-tls.c23
-rw-r--r--src/benchmark.c4
-rw-r--r--src/prime.c8
15 files changed, 82 insertions, 46 deletions
diff --git a/NEWS b/NEWS
index 9138d78d6a..cf95e504b7 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,9 @@ See the end for copying conditions.
it will only list the ciphersuites that are enabled by the given
priority string.
+** libgnutls: Optimizations in Diffie-Hellman parameters generation
+and key exchange.
+
** libgnutls: When session tickets are negotiated and used in a
session, a server will not store that session data into its cache.
diff --git a/lib/auth/anon.c b/lib/auth/anon.c
index 926bab650a..49efb497c6 100644
--- a/lib/auth/anon.c
+++ b/lib/auth/anon.c
@@ -99,7 +99,7 @@ gen_anon_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
_gnutls_dh_set_group (session, g, p);
- ret = _gnutls_dh_common_print_server_kx (session, g, p, data);
+ ret = _gnutls_dh_common_print_server_kx (session, g, p, dh_params->q_bits, data);
if (ret < 0)
{
gnutls_assert ();
diff --git a/lib/auth/dh_common.c b/lib/auth/dh_common.c
index 484fe4fceb..7a93d83789 100644
--- a/lib/auth/dh_common.c
+++ b/lib/auth/dh_common.c
@@ -129,7 +129,7 @@ _gnutls_gen_dh_common_client_kx_int (gnutls_session_t session, gnutls_buffer_st*
int ret;
X = gnutls_calc_dh_secret (&x, session->key->client_g,
- session->key->client_p);
+ session->key->client_p, 0);
if (X == NULL || x == NULL)
{
gnutls_assert ();
@@ -283,17 +283,17 @@ _gnutls_proc_dh_common_server_kx (gnutls_session_t session,
return ret;
}
-/* If the psk flag is set, then an empty psk_identity_hint will
- * be inserted */
int
_gnutls_dh_common_print_server_kx (gnutls_session_t session,
- bigint_t g, bigint_t p, gnutls_buffer_st* data)
+ bigint_t g, bigint_t p, unsigned int q_bits,
+ gnutls_buffer_st* data)
{
- bigint_t x, X;
+ bigint_t x, Y;
int ret;
- X = gnutls_calc_dh_secret (&x, g, p);
- if (X == NULL || x == NULL)
+ /* Y=g^x mod p */
+ Y = gnutls_calc_dh_secret (&x, g, p, q_bits);
+ if (Y == NULL || x == NULL)
{
gnutls_assert ();
return GNUTLS_E_MEMORY_ERROR;
@@ -316,7 +316,7 @@ _gnutls_dh_common_print_server_kx (gnutls_session_t session,
goto cleanup;
}
- ret = _gnutls_buffer_append_mpi(data, 16, X, 0);
+ ret = _gnutls_buffer_append_mpi(data, 16, Y, 0);
if (ret < 0)
{
ret = gnutls_assert_val(ret);
@@ -324,7 +324,7 @@ _gnutls_dh_common_print_server_kx (gnutls_session_t session,
}
cleanup:
- _gnutls_mpi_release (&X);
+ _gnutls_mpi_release (&Y);
return data->length;
}
diff --git a/lib/auth/dh_common.h b/lib/auth/dh_common.h
index 20fc6983db..2ff976a9a4 100644
--- a/lib/auth/dh_common.h
+++ b/lib/auth/dh_common.h
@@ -42,7 +42,8 @@ int _gnutls_proc_dh_common_client_kx (gnutls_session_t session,
bigint_t p, bigint_t g,
gnutls_datum_t* psk_key);
int _gnutls_dh_common_print_server_kx (gnutls_session_t, bigint_t g,
- bigint_t p, gnutls_buffer_st* data);
+ bigint_t p, unsigned int q_bits,
+ gnutls_buffer_st* data);
int _gnutls_proc_dh_common_server_kx (gnutls_session_t session, opaque * data,
size_t _data_size);
diff --git a/lib/auth/dhe.c b/lib/auth/dhe.c
index 5e9d5e0a17..87496af17d 100644
--- a/lib/auth/dhe.c
+++ b/lib/auth/dhe.c
@@ -168,7 +168,7 @@ gen_dhe_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
_gnutls_dh_set_group (session, g, p);
- ret = _gnutls_dh_common_print_server_kx (session, g, p, data);
+ ret = _gnutls_dh_common_print_server_kx (session, g, p, dh_params->q_bits, data);
}
else
{
diff --git a/lib/auth/dhe_psk.c b/lib/auth/dhe_psk.c
index d1417e34de..7170c0b11c 100644
--- a/lib/auth/dhe_psk.c
+++ b/lib/auth/dhe_psk.c
@@ -177,7 +177,7 @@ gen_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
if (ret < 0)
return gnutls_assert_val(ret);
- ret = _gnutls_dh_common_print_server_kx (session, g, p, data);
+ ret = _gnutls_dh_common_print_server_kx (session, g, p, dh_params->q_bits, data);
if (ret < 0)
gnutls_assert ();
diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
index ed89deb39d..a49b48826c 100644
--- a/lib/crypto-backend.h
+++ b/lib/crypto-backend.h
@@ -78,6 +78,7 @@
{
bigint_t g; /* group generator */
bigint_t p; /* prime */
+ int q_bits; /* the number of bits of q */
} gnutls_group_st;
/**
diff --git a/lib/gnutls_dh.c b/lib/gnutls_dh.c
index bd46e546bf..d38856b809 100644
--- a/lib/gnutls_dh.c
+++ b/lib/gnutls_dh.c
@@ -47,13 +47,16 @@
/* returns the public value (X), and the secret (ret_x).
*/
bigint_t
-gnutls_calc_dh_secret (bigint_t * ret_x, bigint_t g, bigint_t prime)
+gnutls_calc_dh_secret (bigint_t * ret_x, bigint_t g, bigint_t prime,
+ unsigned int q_bits)
{
bigint_t e, x = NULL;
- int x_size = _gnutls_mpi_get_nbits (prime) - 1;
- /* The size of the secret key is less than
- * prime/2
- */
+ int x_size;
+
+ if (q_bits == 0)
+ x_size = _gnutls_mpi_get_nbits (prime) - 1;
+ else
+ x_size = q_bits;
if (x_size > MAX_BITS || x_size <= 0)
{
diff --git a/lib/gnutls_dh.h b/lib/gnutls_dh.h
index 990294ef78..5b053705c4 100644
--- a/lib/gnutls_dh.h
+++ b/lib/gnutls_dh.h
@@ -24,7 +24,8 @@
#define GNUTLS_DH_H
const bigint_t *_gnutls_dh_params_to_mpi (gnutls_dh_params_t);
-bigint_t gnutls_calc_dh_secret (bigint_t * ret_x, bigint_t g, bigint_t prime);
+bigint_t gnutls_calc_dh_secret (bigint_t * ret_x, bigint_t g, bigint_t prime,
+ unsigned int q_bits);
bigint_t gnutls_calc_dh_key (bigint_t f, bigint_t x, bigint_t prime);
gnutls_dh_params_t
diff --git a/lib/gnutls_dh_primes.c b/lib/gnutls_dh_primes.c
index c4ea423d75..f4fac9f827 100644
--- a/lib/gnutls_dh_primes.c
+++ b/lib/gnutls_dh_primes.c
@@ -197,6 +197,7 @@ gnutls_dh_params_generate2 (gnutls_dh_params_t params, unsigned int bits)
params->params[0] = group.p;
params->params[1] = group.g;
+ params->q_bits = group.q_bits;
return 0;
}
@@ -223,6 +224,7 @@ gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
{
ASN1_TYPE c2;
int result, need_free = 0;
+ unsigned int q_bits;
gnutls_datum_t _params;
if (format == GNUTLS_X509_FMT_PEM)
@@ -284,6 +286,16 @@ gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
return _gnutls_asn2err (result);
}
+ /* Read q length */
+ result = _gnutls_x509_read_uint (c2, "privateValueLength", &q_bits);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ params->q_bits = 0;
+ }
+ else
+ params->q_bits = q_bits;
+
/* Read PRIME
*/
result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
@@ -380,6 +392,18 @@ gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params,
return _gnutls_asn2err (result);
}
+ if (params->q_bits > 0)
+ result = _gnutls_x509_write_uint32 (c2, "privateValueLength", params->q_bits);
+ else
+ result = asn1_write_value (c2, "privateValueLength", NULL, 0);
+
+ if (result < 0)
+ {
+ gnutls_assert ();
+ asn1_delete_structure (&c2);
+ return _gnutls_asn2err (result);
+ }
+
/* Write the GENERATOR
*/
if ((result = asn1_write_value (c2, "base",
@@ -393,13 +417,6 @@ gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params,
gnutls_free (all_data);
- if ((result = asn1_write_value (c2, "privateValueLength",
- NULL, 0)) != ASN1_SUCCESS)
- {
- gnutls_assert ();
- asn1_delete_structure (&c2);
- return _gnutls_asn2err (result);
- }
if (format == GNUTLS_X509_FMT_DER)
{
@@ -492,7 +509,7 @@ gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params,
* @params: Holds the DH parameters
* @prime: will hold the new prime
* @generator: will hold the new generator
- * @bits: if non null will hold is the prime's number of bits
+ * @bits: if non null will hold the secret key's number of bits
*
* This function will export the pair of prime and generator for use
* in the Diffie-Hellman key exchange. The new parameters will be
@@ -531,7 +548,7 @@ gnutls_dh_params_export_raw (gnutls_dh_params_t params,
}
if (bits)
- *bits = _gnutls_mpi_get_nbits (params->params[0]);
+ *bits = params->q_bits;
return 0;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index d4644d94d7..5ffbb015b1 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -586,6 +586,8 @@ typedef struct gnutls_dh_params_int
/* [0] is the prime, [1] is the generator.
*/
bigint_t params[2];
+ int q_bits; /* length of q in bits. If zero then length is unknown.
+ */
} dh_params_st;
typedef struct
diff --git a/lib/nettle/mpi.c b/lib/nettle/mpi.c
index 322811daf7..0ebdcf4d2d 100644
--- a/lib/nettle/mpi.c
+++ b/lib/nettle/mpi.c
@@ -413,7 +413,7 @@ wrap_nettle_prime_check (bigint_t pp)
*
*/
inline static int
-gen_group (mpz_t * prime, mpz_t * generator, unsigned int nbits)
+gen_group (mpz_t * prime, mpz_t * generator, unsigned int nbits, unsigned int *q_bits)
{
mpz_t q, w, r;
unsigned int p_bytes = nbits / 8;
@@ -520,8 +520,9 @@ gen_group (mpz_t * prime, mpz_t * generator, unsigned int nbits)
}
}
+ *q_bits = wrap_nettle_mpi_get_nbits (&q);
_gnutls_debug_log ("Found prime q of %u bits. Looking for generator...\n",
- wrap_nettle_mpi_get_nbits (&q));
+ *q_bits);
/* finally a prime! Let calculate generator
*/
@@ -585,6 +586,7 @@ wrap_nettle_generate_group (gnutls_group_st * group, unsigned int bits)
int ret;
bigint_t p = wrap_nettle_mpi_new (bits);
bigint_t g;
+ unsigned int q_bits;
if (p == NULL)
{
@@ -600,7 +602,7 @@ wrap_nettle_generate_group (gnutls_group_st * group, unsigned int bits)
return GNUTLS_E_MEMORY_ERROR;
}
- ret = gen_group (p, g, bits);
+ ret = gen_group (p, g, bits, &q_bits);
if (ret < 0)
{
_gnutls_mpi_release (&g);
@@ -611,6 +613,7 @@ wrap_nettle_generate_group (gnutls_group_st * group, unsigned int bits)
group->p = p;
group->g = g;
+ group->q_bits = q_bits;
return 0;
}
diff --git a/src/benchmark-tls.c b/src/benchmark-tls.c
index fcb7e564ee..d2a742de63 100644
--- a/src/benchmark-tls.c
+++ b/src/benchmark-tls.c
@@ -55,9 +55,12 @@
#ifdef PARAMS_1024
const char *pkcs3 =
"-----BEGIN DH PARAMETERS-----\n"
- "MIGHAoGBAO6vCrmts43WnDP4CvqPxehgcmGHdf88C56iMUycJWV21nTfdJbqgdM4\n"
- "O0gT1pLG4ODV2OJQuYvkjklcHWCJ2tFdx9e0YVTWts6O9K1psV1JglWbKXvPGIXF\n"
- "KfVmZg5X7GjtvDwFcmzAL9TL9Jduqpr9UTj+g3ZDW5/GHS/A6wbjAgEC\n"
+ "MIIBCwKBgQCsIrA9BK23OUVIwrC4c65YJ2t8bqoGpJpuISjO07lAbWHWa47Kf9/t\n"
+ "F9ckO2AF6Yj1Y7xS+FSCDeoIZsp0LCq3nAP9Ls25fgHrKSMPQBJt2vd5mUdm90Wr\n"
+ "wCK2YjogQ7YVQlovVHsnJWC6Kf0P+OQ4hrihoBCGSj9sGK3wH57m+wKBgH5xlPNR\n"
+ "pI8E2WBNqB6y4sV3eMGRvygScbbFUFFO1ccmNJl5Y5L/O+fP0ZXtmUJVsSvlY0fp\n"
+ "Kcl6k5WCWMY8h6iHlJ9teHmC4s2jifXtaV759kJXdqrGEjRPEku50y3ANzDLzklW\n"
+ "8R7HcSO397vIdouaUt38FbQESnIWOIZqDtq6AgIAnw==\n"
"-----END DH PARAMETERS-----\n";
/* RSA key of 1024 bits */
@@ -98,13 +101,13 @@ static unsigned char server_key_pem[] =
*/
const char *pkcs3 =
"-----BEGIN DH PARAMETERS-----\n"
- "MIIBPgKBnBw2c5yglfuVfHxYAmWQmLfO1K2sEqTY4panDGgf/aF4HGuGcTfy511c\n"
- "d3+/C7SJuMEM9RwKt503qb9pLEHVbZsXLECGVFcX3c5UAkPKKB/zhcmz6facSLn7\n"
- "o8hLC30DQM9IQ26N7BaOGcEgeya+NGGUk7yC+v+tRiCG2OU/0mQTAx4g7OCVBRAn\n"
- "piJ6yW5kNzNJkKKGOnLXzcXbzwKBnA/aNsM6bmYOx5N2iybHQ0/Dltp8s/2Sw9YY\n"
- "oWBZNLJRCHyB1Q+MH1n3GJ7oEqG0/D9i+byA41I/KNvaaZVK+Oai8pvcdDwdrSxW\n"
- "AMbtukYTxc4eGedtDuwHP55+AlRS+daRZQXbq43aFauPgGiwpm0I+EnMhg25owV2\n"
- "jgL3Ag174DhfvwcMsgC1EO1G0gsxjCc4BD5NKdqvJDNaxw==\n"
+ "MIIBQwKBnQDgLx3SqWyHOfGn/03r1tRwf3pByo3C4V1YIjjDQUoIzn82tRMPEKsL\n"
+ "vos7WXjKgF1+S+T5Y9A7XqivGv1XJ1ZmDvewXVRByxjGRZbkoqCPw4Zv0Uyl9pjV\n"
+ "WaR/Y/emZrN51K0zkdFJCzCt3lPlO3UprnYYHkySRpxTJ4ab5iXRFXETA5rJ5WH0\n"
+ "itGpoR5xb2fR1Gmg5kXCNutkZ9cCgZwqJUZwqKIHJ9cYtzvZXFpjZNgF+mRWyiFr\n"
+ "AQooJbFbVX3o2seJZl3mMqaetaLHF+L8anZFQipNgxenzQgEWEv8FubHXStaOnX1\n"
+ "cwjwwxmCUK4lpfCQZtJ1K3os2JCcNaTBUyxAfiXFIYJmO/os0hFhR6a4EjIlkcq0\n"
+ "yDDLN1weTNOpBPstp1WGHZCsKdJZzgfVvYL6er4zVBtBS0cCAgCg\n"
"-----END DH PARAMETERS-----\n";
static unsigned char server_cert_pem[] =
diff --git a/src/benchmark.c b/src/benchmark.c
index 42f821c473..a5dabc4e28 100644
--- a/src/benchmark.c
+++ b/src/benchmark.c
@@ -102,14 +102,14 @@ void start_benchmark(struct benchmark_st * st)
fprintf (stderr, "error: CreateThread %u\n", GetLastError ());
exit(1);
}
- st->alarm_timeout.QuadPart = (5) * 10000000;
+ st->alarm_timeout.QuadPart = (2) * 10000000;
if (SetWaitableTimer (st->wtimer, &st->alarm_timeout, 0, NULL, NULL, FALSE) == 0)
{
fprintf (stderr, "error: SetWaitableTimer %u\n", GetLastError ());
exit(1);
}
#else
- alarm (5);
+ alarm (2);
#endif
}
diff --git a/src/prime.c b/src/prime.c
index 111337515f..0855a8f3c1 100644
--- a/src/prime.c
+++ b/src/prime.c
@@ -48,6 +48,7 @@ generate_prime (int how, common_info_st * info)
gnutls_dh_params_t dh_params;
gnutls_datum_t p, g;
int bits = get_bits (GNUTLS_PK_DH, info->bits, info->sec_param);
+ unsigned int q_bits = 0;
gnutls_dh_params_init (&dh_params);
@@ -69,7 +70,7 @@ generate_prime (int how, common_info_st * info)
exit (1);
}
- ret = gnutls_dh_params_export_raw (dh_params, &p, &g, NULL);
+ ret = gnutls_dh_params_export_raw (dh_params, &p, &g, &q_bits);
if (ret < 0)
{
fprintf (stderr, "Error exporting parameters: %s\n",
@@ -189,8 +190,9 @@ generate_prime (int how, common_info_st * info)
fprintf (outfile, "%.2x", p.data[i]);
}
- fprintf (outfile, "\n\n");
-
+ if (q_bits > 0)
+ fprintf (outfile, "\n\nRecommended key length: %d bits\n", q_bits);
+ fprintf (outfile, "\n");
}
if (!cparams)