]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Diffie Hellman PKCS #3 parameters now contain the recommended private key size.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 12 Dec 2011 16:46:00 +0000 (17:46 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 12 Dec 2011 16:55:44 +0000 (17:55 +0100)
By using the recommended key size the calculations for the server side are
reduced, giving a 50% increase in DH calculations.

15 files changed:
NEWS
lib/auth/anon.c
lib/auth/dh_common.c
lib/auth/dh_common.h
lib/auth/dhe.c
lib/auth/dhe_psk.c
lib/crypto-backend.h
lib/gnutls_dh.c
lib/gnutls_dh.h
lib/gnutls_dh_primes.c
lib/gnutls_int.h
lib/nettle/mpi.c
src/benchmark-tls.c
src/benchmark.c
src/prime.c

diff --git a/NEWS b/NEWS
index 9138d78d6a2da04104281c3f49c474604218018c..cf95e504b7e5c1d1a3f32adbd6b6d1157026561e 100644 (file)
--- 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.
 
index 926bab650a63f5b944165bc29807e9206ed79504..49efb497c6dd5ae96f625e7e77e56f2138ccb700 100644 (file)
@@ -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 ();
index 484fe4fcebba6828ef50fc30eecbd8f71ac8bca5..7a93d83789cb0f6ed534bc4062a0efdda14586fb 100644 (file)
@@ -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;
 }
index 20fc6983db1785a1bab692357d0051db8459e7d6..2ff976a9a413c66886658f48a3ef8613240a4d30 100644 (file)
@@ -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);
 
index 5e9d5e0a178a88fde7a1d8d4f7ea933fb34df2b0..87496af17d20c7c99bd3010b3502faa31fec696d 100644 (file)
@@ -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
     {
index d1417e34de354895a6baf3cdcd2de4b58956b37b..7170c0b11c7e61527249913b35824cf6c89f4fdb 100644 (file)
@@ -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 ();
 
index ed89deb39d8ebb12cc47ea92abf4fbe60d32e981..a49b48826c145d9e260b16d2517f1386a1637663 100644 (file)
@@ -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;
 
 /**
index bd46e546bf0b3bd2560abd080e3621b8cbdeba2e..d38856b809421a1c5ecbaec60938e29ec2248105 100644 (file)
 /* 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)
     {
index 990294ef787421627e0fc39788d018b7505e582a..5b053705c41bd2789399aa8da7652f890a7e0476 100644 (file)
@@ -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
index c4ea423d75f874fab5f5f5aee7ff157d21258597..f4fac9f82720cada514a874f41451531ba7b9616 100644 (file)
@@ -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;
 
index d4644d94d72e69df18da4fb78d483b8e4257d762..5ffbb015b1ccd6cee685f8d82d50d95d3e399dfb 100644 (file)
@@ -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
index 322811daf723fc2c40aeb9adb193998c838d6d54..0ebdcf4d2da79fe370e83cfb586acb0d9655b183 100644 (file)
@@ -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;
 }
index fcb7e564eebf518c5dae26f7ba1936e0ab30cd45..d2a742de63d87894798bf975148073ec9f36858d 100644 (file)
 #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[] =
index 42f821c473b155d1ec2806363fea2eceab9a2d9f..a5dabc4e2870748ed9876677e95c64799f631c0c 100644 (file)
@@ -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
   
 }
index 111337515facf3126b94f12bdcdece971f5444e3..0855a8f3c17b4b0854d49e1328f20c5e0f21c495 100644 (file)
@@ -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)