Version 2.3.13.
[gnutls.git] / lib / gnutls_dh.c
blob5bf5ec27749f4cf412ba9b13cb795ed7b69b2e76
1 /*
2 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 #include <gnutls_int.h>
26 #include <gnutls_errors.h>
29 /*
30 --Example--
31 you: X = g ^ x mod p;
32 peer:Y = g ^ y mod p;
34 your_key = Y ^ x mod p;
35 his_key = X ^ y mod p;
37 // generate our secret and the public value (X) for it
38 X = gnutls_calc_dh_secret(&x, g, p);
39 // now we can calculate the shared secret
40 key = gnutls_calc_dh_key(Y, x, g, p);
41 _gnutls_mpi_release(x);
42 _gnutls_mpi_release(g);
45 #define MAX_BITS 18000
47 /* returns the public value (X), and the secret (ret_x).
49 mpi_t
50 gnutls_calc_dh_secret (mpi_t * ret_x, mpi_t g, mpi_t prime)
52 mpi_t e, x;
53 int x_size = _gnutls_mpi_get_nbits (prime) - 1;
54 /* The size of the secret key is less than
55 * prime/2
58 if (x_size > MAX_BITS || x_size <= 0)
60 gnutls_assert ();
61 return NULL;
64 x = _gnutls_mpi_new (x_size);
65 if (x == NULL)
67 gnutls_assert ();
68 if (ret_x)
69 *ret_x = NULL;
71 return NULL;
74 /* FIXME: (x_size/8)*8 is there to overcome a bug in libgcrypt
75 * which does not really check the bits given but the bytes.
79 _gnutls_mpi_randomize (x, (x_size / 8) * 8, GCRY_STRONG_RANDOM);
80 /* Check whether x is zero.
83 while (_gnutls_mpi_cmp_ui (x, 0) == 0);
85 e = _gnutls_mpi_alloc_like (prime);
86 if (e == NULL)
88 gnutls_assert ();
89 if (ret_x)
90 *ret_x = NULL;
92 _gnutls_mpi_release (&x);
93 return NULL;
96 _gnutls_mpi_powm (e, g, x, prime);
98 if (ret_x)
99 *ret_x = x;
100 else
101 _gnutls_mpi_release (&x);
102 return e;
106 mpi_t
107 gnutls_calc_dh_key (mpi_t f, mpi_t x, mpi_t prime)
109 mpi_t k;
110 int bits;
112 bits = _gnutls_mpi_get_nbits (prime);
113 if (bits <= 0 || bits > MAX_BITS)
115 gnutls_assert ();
116 return NULL;
119 k = _gnutls_mpi_alloc_like (prime);
120 if (k == NULL)
121 return NULL;
122 _gnutls_mpi_powm (k, f, x, prime);
123 return k;
127 * _gnutls_get_dh_params - Returns the DH parameters pointer
128 * @dh_params: is an DH parameters structure, or NULL.
129 * @func: is a callback function to receive the parameters or NULL.
130 * @session: a gnutls session.
132 * This function will return the dh parameters pointer.
135 gnutls_dh_params_t
136 _gnutls_get_dh_params (gnutls_dh_params_t dh_params,
137 gnutls_params_function * func,
138 gnutls_session_t session)
140 gnutls_params_st params;
141 int ret;
143 /* if cached return the cached */
144 if (session->internals.params.dh_params)
145 return session->internals.params.dh_params;
147 if (dh_params)
149 session->internals.params.dh_params = dh_params;
151 else if (func)
153 ret = func (session, GNUTLS_PARAMS_DH, &params);
154 if (ret == 0 && params.type == GNUTLS_PARAMS_DH)
156 session->internals.params.dh_params = params.params.dh;
157 session->internals.params.free_dh_params = params.deinit;
161 return session->internals.params.dh_params;