]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
DH key exchange uses the _gnutls_pk_derive and _gnutls_pk_generate_key functions.
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 28 Nov 2013 12:41:21 +0000 (13:41 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 28 Nov 2013 13:23:15 +0000 (14:23 +0100)
This allows handling DH key generation in the crypto backend files.

12 files changed:
lib/auth/anon.c
lib/auth/dh_common.c
lib/auth/dh_common.h
lib/auth/dhe.c
lib/auth/dhe_psk.c
lib/auth/srp.c
lib/crypto-backend.h
lib/gnutls_dh.c
lib/gnutls_dh.h
lib/gnutls_int.h
lib/gnutls_state.c
lib/nettle/pk.c

index 54548300ebbcb8c9825b288255f518ba1a20f5ce..f8b9f0ecb5735c3904d9b07b663549f7f2b1718f 100644 (file)
@@ -96,9 +96,12 @@ gen_anon_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
 
        _gnutls_dh_set_group(session, g, p);
 
+       ret = _gnutls_set_dh_pk_params(session, g, p, dh_params->q_bits);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
        ret =
-           _gnutls_dh_common_print_server_kx(session, g, p,
-                                             dh_params->q_bits, data);
+           _gnutls_dh_common_print_server_kx(session, data);
        if (ret < 0) {
                gnutls_assert();
        }
index 5cc0d4cec097a034bc5cb5d456b693f95919df8a..434515af200fa727e9754312df111beb919886ad 100644 (file)
@@ -34,6 +34,7 @@
 #include <gnutls_datum.h>
 #include <gnutls_x509.h>
 #include <gnutls_state.h>
+#include <gnutls_pk.h>
 #include <auth/dh_common.h>
 #include <algorithms.h>
 #include <auth/psk.h>
@@ -60,7 +61,10 @@ _gnutls_proc_dh_common_client_kx(gnutls_session_t session,
        size_t _n_Y;
        int ret;
        ssize_t data_size = _data_size;
-
+       gnutls_datum_t tmp_dh_key = {NULL, 0};
+       gnutls_pk_params_st peer_pub;
+       
+       gnutls_pk_params_init(&peer_pub);
 
        DECR_LEN(data_size, 2);
        n_Y = _gnutls_read_uint16(&data[0]);
@@ -74,43 +78,37 @@ _gnutls_proc_dh_common_client_kx(gnutls_session_t session,
 
        _gnutls_dh_set_peer_public(session, session->key.client_Y);
 
-       ret =
-           gnutls_calc_dh_key(&session->key.KEY, session->key.client_Y,
-                              session->key.dh_secret, p);
-       if (ret < 0)
-               return gnutls_assert_val(ret);
+       peer_pub.params[DH_Y] = session->key.client_Y;
 
-       _gnutls_mpi_release(&session->key.client_Y);
-       zrelease_temp_mpi_key(&session->key.dh_secret);
+       /* calculate the key after calculating the message */
+       ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub);
+       if (ret < 0) {
+               gnutls_assert();
+               goto error;
+       }
 
 
        if (psk_key == NULL) {
-               ret =
-                   _gnutls_mpi_dprint(session->key.KEY,
-                                      &session->key.key);
+               session->key.key.data = tmp_dh_key.data;
+               session->key.key.size = tmp_dh_key.size;
        } else {                /* In DHE_PSK the key is set differently */
-
-               gnutls_datum_t tmp_dh_key;
-               ret = _gnutls_mpi_dprint(session->key.KEY, &tmp_dh_key);
-               if (ret < 0) {
-                       gnutls_assert();
-                       return ret;
-               }
-
                ret =
                    _gnutls_set_psk_session_key(session, psk_key,
                                                &tmp_dh_key);
                _gnutls_free_temp_key_datum(&tmp_dh_key);
-
        }
-
-       zrelease_temp_mpi_key(&session->key.KEY);
-
+       
        if (ret < 0) {
-               return ret;
+               gnutls_assert();
+               goto error;
        }
 
-       return 0;
+       ret = 0;
+error:
+       _gnutls_mpi_release(&session->key.client_Y);
+       gnutls_pk_params_clear(&session->key.dh_params);
+
+       return ret;
 }
 
 int _gnutls_gen_dh_common_client_kx(gnutls_session_t session,
@@ -124,62 +122,47 @@ _gnutls_gen_dh_common_client_kx_int(gnutls_session_t session,
                                    gnutls_buffer_st * data,
                                    gnutls_datum_t * pskkey)
 {
-       bigint_t x = NULL, Y = NULL;
        int ret;
+       gnutls_pk_params_st peer_pub;
+       gnutls_datum_t tmp_dh_key = {NULL, 0};
+       
+       gnutls_pk_params_init(&peer_pub);
 
-       ret = gnutls_calc_dh_secret(&Y, &x, session->key.client_g,
-                                   session->key.client_p, 0);
-       if (ret < 0) {
-               gnutls_assert();
-               goto error;
-       }
+       ret =
+           _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0,
+                                    &session->key.dh_params);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
 
-       _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(x));
+       _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_X]));
 
-       ret = _gnutls_buffer_append_mpi(data, 16, Y, 0);
+       ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_Y], 0);
        if (ret < 0) {
                gnutls_assert();
                goto error;
        }
+       
+       peer_pub.params[DH_Y] = session->key.client_Y;
 
        /* calculate the key after calculating the message */
-       ret =
-           gnutls_calc_dh_key(&session->key.KEY, session->key.client_Y, x,
-                              session->key.client_p);
+       ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub);
        if (ret < 0) {
                gnutls_assert();
                goto error;
        }
 
-       /* THESE SHOULD BE DISCARDED */
-       _gnutls_mpi_release(&session->key.client_Y);
-       _gnutls_mpi_release(&session->key.client_p);
-       _gnutls_mpi_release(&session->key.client_g);
-
        if (_gnutls_cipher_suite_get_kx_algo
            (session->security_parameters.cipher_suite)
            != GNUTLS_KX_DHE_PSK) {
-               ret =
-                   _gnutls_mpi_dprint(session->key.KEY,
-                                      &session->key.key);
+               session->key.key.data = tmp_dh_key.data;
+               session->key.key.size = tmp_dh_key.size;
        } else {                /* In DHE_PSK the key is set differently */
-
-               gnutls_datum_t tmp_dh_key;
-
-               ret = _gnutls_mpi_dprint(session->key.KEY, &tmp_dh_key);
-               if (ret < 0) {
-                       gnutls_assert();
-                       goto error;
-               }
-
                ret =
                    _gnutls_set_psk_session_key(session, pskkey,
                                                &tmp_dh_key);
                _gnutls_free_temp_key_datum(&tmp_dh_key);
        }
 
-       zrelease_temp_mpi_key(&session->key.KEY);
-
        if (ret < 0) {
                gnutls_assert();
                goto error;
@@ -188,11 +171,32 @@ _gnutls_gen_dh_common_client_kx_int(gnutls_session_t session,
        ret = data->length;
 
       error:
-       zrelease_temp_mpi_key(&x);
-       _gnutls_mpi_release(&Y);
+       gnutls_pk_params_clear(&session->key.dh_params);
        return ret;
 }
 
+int _gnutls_set_dh_pk_params(gnutls_session_t session, bigint_t g, bigint_t p,
+                               unsigned q_bits)
+{
+       gnutls_pk_params_init(&session->key.dh_params);
+
+       session->key.dh_params.params[DH_G] = _gnutls_mpi_copy(g);
+       if (session->key.dh_params.params[DH_G] == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+       
+       session->key.dh_params.params[DH_P] = _gnutls_mpi_copy(p);
+       if (session->key.dh_params.params[DH_P] == NULL) {
+               _gnutls_mpi_release(&session->key.dh_params.params[DH_G]);
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+       }
+
+       session->key.dh_params.params_nr = 3; /* include empty q */
+       session->key.dh_params.algo = GNUTLS_PK_DH;
+       session->key.dh_params.flags = q_bits;
+       
+       return 0;
+}
+
 /* Returns the bytes parsed */
 int
 _gnutls_proc_dh_common_server_kx(gnutls_session_t session,
@@ -205,6 +209,8 @@ _gnutls_proc_dh_common_server_kx(gnutls_session_t session,
        uint8_t *data_Y;
        int i, bits, ret;
        ssize_t data_size = _data_size;
+       
+       gnutls_pk_params_init(&session->key.dh_params);
 
        i = 0;
 
@@ -240,14 +246,17 @@ _gnutls_proc_dh_common_server_kx(gnutls_session_t session,
                return GNUTLS_E_MPI_SCAN_FAILED;
        }
 
-       if (_gnutls_mpi_scan_nz(&session->key.client_g, data_g, _n_g) != 0) {
+       if (_gnutls_mpi_scan_nz(&session->key.dh_params.params[DH_G], data_g, _n_g) != 0) {
                gnutls_assert();
                return GNUTLS_E_MPI_SCAN_FAILED;
        }
-       if (_gnutls_mpi_scan_nz(&session->key.client_p, data_p, _n_p) != 0) {
+
+       if (_gnutls_mpi_scan_nz(&session->key.dh_params.params[DH_P], data_p, _n_p) != 0) {
                gnutls_assert();
                return GNUTLS_E_MPI_SCAN_FAILED;
        }
+       session->key.dh_params.params_nr = 3; /* include empty q */
+       session->key.dh_params.algo = GNUTLS_PK_DH;
 
        bits = _gnutls_dh_get_min_prime_bits(session);
        if (bits < 0) {
@@ -255,20 +264,19 @@ _gnutls_proc_dh_common_server_kx(gnutls_session_t session,
                return bits;
        }
 
-       if (_gnutls_mpi_get_nbits(session->key.client_p) < (size_t) bits) {
+       if (_gnutls_mpi_get_nbits(session->key.dh_params.params[DH_P]) < (size_t) bits) {
                /* the prime used by the peer is not acceptable
                 */
                gnutls_assert();
                _gnutls_debug_log
                    ("Received a prime of %u bits, limit is %u\n",
-                    (unsigned) _gnutls_mpi_get_nbits(session->key.
-                                                     client_p),
+                    (unsigned) _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_P]),
                     (unsigned) bits);
                return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
        }
 
-       _gnutls_dh_set_group(session, session->key.client_g,
-                            session->key.client_p);
+       _gnutls_dh_set_group(session, session->key.dh_params.params[DH_G],
+                            session->key.dh_params.params[DH_P]);
        _gnutls_dh_set_peer_public(session, session->key.client_Y);
 
        ret = n_Y + n_p + n_g + 6;
@@ -278,45 +286,41 @@ _gnutls_proc_dh_common_server_kx(gnutls_session_t session,
 
 int
 _gnutls_dh_common_print_server_kx(gnutls_session_t session,
-                                 bigint_t g, bigint_t p,
-                                 unsigned int q_bits,
                                  gnutls_buffer_st * data)
 {
-       bigint_t x, Y;
        int ret;
+       unsigned q_bits = session->key.dh_params.flags;
 
        /* Y=g^x mod p */
-       ret = gnutls_calc_dh_secret(&Y, &x, g, p, q_bits);
-       if (ret < 0) {
-               gnutls_assert();
-               return ret;
-       }
+       ret =
+           _gnutls_pk_generate_keys(GNUTLS_PK_DH, q_bits,
+                                    &session->key.dh_params);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
 
-       session->key.dh_secret = x;
-       _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(x));
+       _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_X]));
 
-       ret = _gnutls_buffer_append_mpi(data, 16, p, 0);
+       ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_P], 0);
        if (ret < 0) {
                gnutls_assert();
                goto cleanup;
        }
 
-       ret = _gnutls_buffer_append_mpi(data, 16, g, 0);
+       ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_G], 0);
        if (ret < 0) {
                gnutls_assert();
                goto cleanup;
        }
 
-       ret = _gnutls_buffer_append_mpi(data, 16, Y, 0);
+       ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_Y], 0);
        if (ret < 0) {
                gnutls_assert();
                goto cleanup;
        }
 
        ret = data->length;
-cleanup:
-       _gnutls_mpi_release(&Y);
 
+cleanup:
        return ret;
 }
 
index 8bfaaaecffa6e13e780e8c60d9df9c23c90ba0d7..016588062c88b2b86e280e11ece4889b80df851f 100644 (file)
@@ -34,6 +34,8 @@ typedef struct {
 } dh_info_st;
 
 void _gnutls_free_dh_info(dh_info_st * dh);
+int _gnutls_set_dh_pk_params(gnutls_session_t session, bigint_t g, bigint_t p,
+       unsigned q_bits);
 int _gnutls_gen_dh_common_client_kx_int(gnutls_session_t,
                                        gnutls_buffer_st *,
                                        gnutls_datum_t * pskkey);
@@ -42,8 +44,7 @@ int _gnutls_proc_dh_common_client_kx(gnutls_session_t session,
                                     uint8_t * data, size_t _data_size,
                                     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, unsigned int q_bits,
+int _gnutls_dh_common_print_server_kx(gnutls_session_t, 
                                      gnutls_buffer_st * data);
 int _gnutls_proc_dh_common_server_kx(gnutls_session_t session,
                                     uint8_t * data, size_t _data_size);
index 546194cdca8f2ba9b101539fa146f7f748e9c8da..6b96f5cad5ffcebc0038d766534b1669eda4106f 100644 (file)
@@ -119,9 +119,12 @@ gen_dhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
 
        _gnutls_dh_set_group(session, g, p);
 
+       ret = _gnutls_set_dh_pk_params(session, g, p, dh_params->q_bits);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
        ret =
-           _gnutls_dh_common_print_server_kx(session, g, p,
-                                             dh_params->q_bits, data);
+           _gnutls_dh_common_print_server_kx(session, data);
        if (ret < 0) {
                gnutls_assert();
                return ret;
index a6edffa0b4648912f3f0e075606515321bfc2550..66e741c9e3d5d971440fe45cd32b69fad3f14afa 100644 (file)
@@ -222,9 +222,12 @@ gen_dhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
        if (ret < 0)
                return gnutls_assert_val(ret);
 
+       ret = _gnutls_set_dh_pk_params(session, g, p, dh_params->q_bits);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
        ret =
-           _gnutls_dh_common_print_server_kx(session, g, p,
-                                             dh_params->q_bits, data);
+           _gnutls_dh_common_print_server_kx(session, data);
        if (ret < 0)
                gnutls_assert();
 
index 520f906cd70bde8fe0af4df91c67bda563f871f8..702b94052c34518521622ea0e42c597028d76e3b 100644 (file)
@@ -57,10 +57,10 @@ const mod_auth_st srp_auth_struct = {
 #define B session->key.B
 #define _a session->key.a
 #define A session->key.A
-#define N session->key.client_p
-#define G session->key.client_g
+#define N session->key.srp_p
+#define G session->key.srp_g
 #define V session->key.x
-#define S session->key.KEY
+#define S session->key.srp_key
 
 /* Checks if a%n==0,+1,-1%n which is a fatal srp error.
  * Returns a proper error code in that case, and 0 when
@@ -309,7 +309,7 @@ _gnutls_gen_srp_client_kx(gnutls_session_t session,
        zrelease_temp_mpi_key(&session->key.u);
        zrelease_temp_mpi_key(&B);
 
-       ret = _gnutls_mpi_dprint(session->key.KEY, &session->key.key);
+       ret = _gnutls_mpi_dprint(session->key.srp_key, &session->key.key);
        zrelease_temp_mpi_key(&S);
 
        if (ret < 0) {
@@ -384,7 +384,7 @@ _gnutls_proc_srp_client_kx(gnutls_session_t session, uint8_t * data,
        zrelease_temp_mpi_key(&session->key.u);
        zrelease_temp_mpi_key(&B);
 
-       ret = _gnutls_mpi_dprint(session->key.KEY, &session->key.key);
+       ret = _gnutls_mpi_dprint(session->key.srp_key, &session->key.key);
        zrelease_temp_mpi_key(&S);
 
        if (ret < 0) {
index e273c0da321e22094c3690ff93d0190a22c4d77d..a497f5614628edfa762ab9d14dae772df29c7260 100644 (file)
@@ -196,6 +196,7 @@ void gnutls_pk_params_init(gnutls_pk_params_st * p);
 
 /* parameters should not be larger than this limit */
 #define DSA_PUBLIC_PARAMS 4
+#define DH_PUBLIC_PARAMS 4
 #define RSA_PUBLIC_PARAMS 2
 #define ECC_PUBLIC_PARAMS 2
 
@@ -204,6 +205,7 @@ void gnutls_pk_params_init(gnutls_pk_params_st * p);
 
 /* parameters should not be larger than this limit */
 #define DSA_PRIVATE_PARAMS 5
+#define DH_PRIVATE_PARAMS 5
 #define RSA_PRIVATE_PARAMS 8
 #define ECC_PRIVATE_PARAMS 3
 
@@ -241,6 +243,8 @@ void gnutls_pk_params_init(gnutls_pk_params_st * p);
  *  [3] is y (public key)
  *  [4] is x (private key only)
  *
+ * DH: as DSA
+ *
  * ECC:
  *  [0] is prime
  *  [1] is order
@@ -263,6 +267,12 @@ void gnutls_pk_params_init(gnutls_pk_params_st * p);
 #define DSA_Y 3
 #define DSA_X 4
 
+#define DH_P 0
+#define DH_Q 1
+#define DH_G 2
+#define DH_Y 3
+#define DH_X 4
+
 #define RSA_MODULUS 0
 #define RSA_PUB 1
 #define RSA_PRIV 2
index da40cffe348af5d1a5bfb3adea22d8ccac3944d7..8cffe92e0e4ff49c203b2ecbbfbfa2f7628fe28c 100644 (file)
 #include <gnutls_errors.h>
 #include <gnutls_dh.h>
 
-
-/* 
-       --Example-- 
-       you: X = g ^ x mod p;
-       peer:Y = g ^ y mod p;
-
-       your_key = Y ^ x mod p;
-       his_key  = X ^ y mod p;
-
-//      generate our secret and the public value (X) for it
-       gnutls_calc_dh_secret(&Y, &X, g, p);
-//      now we can calculate the shared secret
-       key = gnutls_calc_dh_key(Y, x, g, p);
-       _gnutls_mpi_release(x);
-       _gnutls_mpi_release(g);
-*/
-
-#define MAX_BITS 18000
-
-/* returns the public value (Y), and the secret (X).
- */
-int
-gnutls_calc_dh_secret(bigint_t * ret_y, bigint_t * ret_x, bigint_t g,
-                     bigint_t prime, unsigned int q_bits)
-{
-       bigint_t e = NULL, x = NULL;
-       unsigned int x_size;
-       int ret;
-
-       if (q_bits == 0) {
-               x_size = _gnutls_mpi_get_nbits(prime);
-               if (x_size > 0)
-                       x_size--;
-       } else
-               x_size = q_bits;
-
-       if (x_size > MAX_BITS || x_size == 0) {
-               gnutls_assert();
-               return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
-       }
-
-       x = _gnutls_mpi_new(x_size + 64);
-       if (x == NULL) {
-               gnutls_assert();
-               ret = GNUTLS_E_MEMORY_ERROR;
-               goto fail;
-       }
-
-       e = _gnutls_mpi_alloc_like(prime);
-       if (e == NULL) {
-               gnutls_assert();
-               ret = GNUTLS_E_MEMORY_ERROR;
-               goto fail;
-       }
-
-       do {
-               if (_gnutls_mpi_random_modp(x, prime, GNUTLS_RND_RANDOM) ==
-                   NULL) {
-                       gnutls_assert();
-                       ret = GNUTLS_E_INTERNAL_ERROR;
-                       goto fail;
-               }
-
-               _gnutls_mpi_powm(e, g, x, prime);
-       }
-       while (_gnutls_mpi_cmp_ui(e, 1) == 0);
-
-       *ret_x = x;
-       *ret_y = e;
-
-       return 0;
-
-      fail:
-       if (x)
-               _gnutls_mpi_release(&x);
-       if (e)
-               _gnutls_mpi_release(&e);
-       return ret;
-
-}
-
-/* returns f^x mod prime 
- */
-int
-gnutls_calc_dh_key(bigint_t * key, bigint_t f, bigint_t x, bigint_t prime)
-{
-       bigint_t k, ff;
-       unsigned int bits;
-       int ret;
-
-       ff = _gnutls_mpi_modm(NULL, f, prime);
-       _gnutls_mpi_add_ui(ff, ff, 1);
-
-       /* check if f==0,1,p-1. 
-        * or (ff=f+1) equivalently ff==1,2,p */
-       if ((_gnutls_mpi_cmp_ui(ff, 2) == 0)
-           || (_gnutls_mpi_cmp_ui(ff, 1) == 0)
-           || (_gnutls_mpi_cmp(ff, prime) == 0)) {
-               gnutls_assert();
-               ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
-               goto cleanup;
-       }
-
-       bits = _gnutls_mpi_get_nbits(prime);
-       if (bits == 0 || bits > MAX_BITS) {
-               gnutls_assert();
-               ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
-               goto cleanup;
-       }
-
-       k = _gnutls_mpi_alloc_like(prime);
-       if (k == NULL) {
-               gnutls_assert();
-               ret = GNUTLS_E_MEMORY_ERROR;
-               goto cleanup;
-       }
-
-       _gnutls_mpi_powm(k, f, x, prime);
-
-       *key = k;
-
-       ret = 0;
-      cleanup:
-       _gnutls_mpi_release(&ff);
-
-       return ret;
-}
-
 /*-
  * _gnutls_get_dh_params - Returns the DH parameters pointer
  * @dh_params: is an DH parameters structure, or NULL.
index fec2ec82820d47c5a70c34602f0269ab40392db0..7bc7bec125768bb87fe8b1f63546b634a63932da 100644 (file)
 #define GNUTLS_DH_H
 
 const bigint_t *_gnutls_dh_params_to_mpi(gnutls_dh_params_t);
-int gnutls_calc_dh_secret(bigint_t * ret_y, bigint_t * ret_x, bigint_t g,
-                         bigint_t, unsigned int q_bits);
-int gnutls_calc_dh_key(bigint_t * key, bigint_t f, bigint_t x,
-                      bigint_t prime);
 
 gnutls_dh_params_t
 _gnutls_get_dh_params(gnutls_dh_params_t dh_params,
index 21d2fc938b8938a84273f19c78df2ddae86daf27..1304b8ff67a2ed283eb4b0b6e39666bf2b3b7dfa 100644 (file)
@@ -381,12 +381,15 @@ struct gnutls_key_st {
 
        /* For DH KX */
        gnutls_datum_t key;
-       bigint_t KEY;
+       
+       /* For DH KX */
+       gnutls_pk_params_st dh_params;
        bigint_t client_Y;
-       bigint_t client_g;
-       bigint_t client_p;
-       bigint_t dh_secret;
        /* for SRP */
+
+       bigint_t srp_key;
+       bigint_t srp_g;
+       bigint_t srp_p;
        bigint_t A;
        bigint_t B;
        bigint_t u;
index 3afec2f8e309ee34425f0072e4d9657240c657c7..7fae162c7242792819104c85fc9a55f91b9ca0d5 100644 (file)
@@ -467,13 +467,15 @@ void gnutls_deinit(gnutls_session_t session)
        _gnutls_selected_certs_deinit(session);
 
        gnutls_pk_params_release(&session->key.ecdh_params);
+       gnutls_pk_params_release(&session->key.dh_params);
        zrelease_temp_mpi_key(&session->key.ecdh_x);
        zrelease_temp_mpi_key(&session->key.ecdh_y);
 
-       zrelease_temp_mpi_key(&session->key.KEY);
        zrelease_temp_mpi_key(&session->key.client_Y);
-       zrelease_temp_mpi_key(&session->key.client_p);
-       zrelease_temp_mpi_key(&session->key.client_g);
+
+       zrelease_temp_mpi_key(&session->key.srp_p);
+       zrelease_temp_mpi_key(&session->key.srp_g);
+       zrelease_temp_mpi_key(&session->key.srp_key);
 
        zrelease_temp_mpi_key(&session->key.u);
        zrelease_temp_mpi_key(&session->key.a);
@@ -486,7 +488,6 @@ void gnutls_deinit(gnutls_session_t session)
        zrelease_temp_mpi_key(&session->key.rsa[0]);
        zrelease_temp_mpi_key(&session->key.rsa[1]);
 
-       zrelease_temp_mpi_key(&session->key.dh_secret);
        _gnutls_free_temp_key_datum(&session->key.key);
 
        gnutls_free(session);
index 5e9c4f56952059db54ad0f6e047836bb11efee7e..c9591496a024c8c6c92d3c77b4902647a2575442 100644 (file)
@@ -81,12 +81,14 @@ static void
 _dsa_params_to_pubkey(const gnutls_pk_params_st * pk_params,
                      struct dsa_public_key *pub)
 {
-       memcpy(&pub->p, pk_params->params[0], sizeof(mpz_t));
-       memcpy(&pub->q, pk_params->params[1], sizeof(mpz_t));
-       memcpy(&pub->g, pk_params->params[2], sizeof(mpz_t));
+       memcpy(&pub->p, pk_params->params[DSA_P], sizeof(mpz_t));
+
+       if (pk_params->params[DSA_Q])
+               memcpy(&pub->q, pk_params->params[DSA_Q], sizeof(mpz_t));
+       memcpy(&pub->g, pk_params->params[DSA_G], sizeof(mpz_t));
        
-       if (pk_params->params[3] != NULL)
-               memcpy(&pub->y, pk_params->params[3], sizeof(mpz_t));
+       if (pk_params->params[DSA_Y] != NULL)
+               memcpy(&pub->y, pk_params->params[DSA_Y], sizeof(mpz_t));
 }
 
 static void
@@ -165,6 +167,11 @@ ecc_shared_secret(struct ecc_scalar *private_key,
        return;
 }
 
+#define MAX_DH_BITS 16*1024
+
+/* This is used for DH or ECDH key derivation. In DH for example
+ * it is given the peers Y and our x, and calculates Y^x 
+ */
 static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
                                  gnutls_datum_t * out,
                                  const gnutls_pk_params_st * priv,
@@ -173,6 +180,60 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
        int ret;
 
        switch (algo) {
+       case GNUTLS_PK_DH: {
+               bigint_t f, x, prime;
+               bigint_t k = NULL, ff;
+               unsigned int bits;
+               
+               f = pub->params[DH_Y];
+               x = priv->params[DH_X];
+               prime = priv->params[DH_P];
+
+               ff = _gnutls_mpi_modm(NULL, f, prime);
+               _gnutls_mpi_add_ui(ff, ff, 1);
+
+               /* check if f==0,1,p-1. 
+                * or (ff=f+1) equivalently ff==1,2,p */
+               if ((_gnutls_mpi_cmp_ui(ff, 2) == 0)
+                   || (_gnutls_mpi_cmp_ui(ff, 1) == 0)
+                   || (_gnutls_mpi_cmp(ff, prime) == 0)) {
+                       gnutls_assert();
+                       ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+                       goto dh_cleanup;
+               }
+
+               /* prevent denial of service */
+               bits = _gnutls_mpi_get_nbits(prime);
+               if (bits == 0 || bits > MAX_DH_BITS) {
+                       gnutls_assert();
+                       ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+                       goto dh_cleanup;
+               }
+
+               k = _gnutls_mpi_alloc_like(prime);
+               if (k == NULL) {
+                       gnutls_assert();
+                       ret = GNUTLS_E_MEMORY_ERROR;
+                       goto dh_cleanup;
+               }
+
+               _gnutls_mpi_powm(k, f, x, prime);
+               
+               ret = _gnutls_mpi_dprint(k, out);
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto dh_cleanup;
+               }
+
+               ret = 0;
+dh_cleanup:
+               _gnutls_mpi_release(&ff);
+               zrelease_temp_mpi_key(&k);
+               if (ret < 0)
+                       goto cleanup;
+               
+               break;
+       }
        case GNUTLS_PK_EC:
                {
                        struct ecc_scalar ecc_priv;
@@ -442,8 +503,8 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
                        if (hash_len > vdata->size) {
                                gnutls_assert();
                                _gnutls_debug_log
-                                   ("Security level of algorithm requires hash %s(%d) or better\n",
-                                    _gnutls_mac_get_name(me), hash_len);
+                                   ("Security level of algorithm requires hash %s(%d) or better (have: %d)\n",
+                                    _gnutls_mac_get_name(me), hash_len, (int)vdata->size);
                                hash_len = vdata->size;
                        }
 
@@ -792,6 +853,9 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo,
        return ret;
 }
 
+/* To generate a DH key either q must be set in the params or
+ * level should be set to the number of required bits.
+ */
 static int
 wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
                               unsigned int level /*bits */ ,
@@ -807,19 +871,33 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
                        struct dsa_public_key pub;
                        mpz_t r;
                        mpz_t x, y;
+                       unsigned have_q = 0;
                        
                        if (algo != params->algo)
                                return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
                        _dsa_params_to_pubkey(params, &pub);
+                       
+                       if (params->params[DSA_Q] != NULL)
+                               have_q = 1;
+                               
+                       if (algo == GNUTLS_PK_DSA && have_q == 0)
+                               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
                        mpz_init(r);
                        mpz_init(x);
                        mpz_init(y);
-                       mpz_set(r, pub.q);
-                       mpz_sub_ui(r, r, 2);
-                       nettle_mpz_random(x, NULL, rnd_func, r);
-                       mpz_add_ui(x, x, 1);
+                       
+                       if (have_q) {
+                               mpz_set(r, pub.q);
+                               mpz_sub_ui(r, r, 2);
+                               nettle_mpz_random(x, NULL, rnd_func, r);
+                               mpz_add_ui(x, x, 1);
+                       } else {
+                               if (level == 0)
+                                       level = mpz_sizeinbase(pub.p, 2);
+                               nettle_mpz_random_size(x, NULL, rnd_func, level);
+                       }
 
                        mpz_powm(y, pub.g, x, pub.p);