2 * Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
27 * and Anonymous DH key exchange(DHA). These are used in the handshake
28 * procedure of the certificate and anoymous authentication.
31 #include "gnutls_int.h"
32 #include "gnutls_auth.h"
33 #include "gnutls_errors.h"
34 #include "gnutls_dh.h"
35 #include "gnutls_num.h"
36 #include "gnutls_sig.h"
37 #include <gnutls_datum.h>
38 #include <gnutls_x509.h>
39 #include <gnutls_state.h>
40 #include <auth_dh_common.h>
41 #include <gnutls_algorithms.h>
44 /* Frees the dh_info_st structure.
47 _gnutls_free_dh_info (dh_info_st * dh)
50 _gnutls_free_datum (&dh->prime);
51 _gnutls_free_datum (&dh->generator);
52 _gnutls_free_datum (&dh->public_key);
56 _gnutls_proc_dh_common_client_kx (gnutls_session_t session,
57 opaque * data, size_t _data_size,
58 bigint_t g, bigint_t p)
63 ssize_t data_size = _data_size;
66 DECR_LEN (data_size, 2);
67 n_Y = _gnutls_read_uint16 (&data[0]);
70 DECR_LEN (data_size, n_Y);
71 if (_gnutls_mpi_scan_nz (&session->key->client_Y, &data[2], _n_Y))
74 return GNUTLS_E_MPI_SCAN_FAILED;
77 _gnutls_dh_set_peer_public (session, session->key->client_Y);
80 gnutls_calc_dh_key (session->key->client_Y, session->key->dh_secret, p);
82 if (session->key->KEY == NULL)
85 return GNUTLS_E_MEMORY_ERROR;
88 _gnutls_mpi_release (&session->key->client_Y);
89 _gnutls_mpi_release (&session->key->dh_secret);
92 if (_gnutls_cipher_suite_get_kx_algo
93 (&session->security_parameters.current_cipher_suite)
96 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
98 else /* In DHE_PSK the key is set differently */
100 gnutls_datum_t tmp_dh_key;
101 ret = _gnutls_mpi_dprint (session->key->KEY, &tmp_dh_key);
108 ret = _gnutls_set_psk_session_key (session, NULL, &tmp_dh_key);
109 _gnutls_free_datum (&tmp_dh_key);
113 _gnutls_mpi_release (&session->key->KEY);
123 int _gnutls_gen_dh_common_client_kx (gnutls_session_t session, opaque** data)
125 return _gnutls_gen_dh_common_client_kx_int(session, data, NULL);
129 _gnutls_gen_dh_common_client_kx_int (gnutls_session_t session, opaque ** data, gnutls_datum_t* pskkey)
131 bigint_t x = NULL, X = NULL;
137 X = gnutls_calc_dh_secret (&x, session->key->client_g,
138 session->key->client_p);
139 if (X == NULL || x == NULL)
142 ret = GNUTLS_E_MEMORY_ERROR;
146 _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));
148 _gnutls_mpi_print (X, NULL, &n_X);
149 (*data) = gnutls_malloc (n_X + 2);
152 ret = GNUTLS_E_MEMORY_ERROR;
156 _gnutls_mpi_print (X, &(*data)[2], &n_X);
157 _gnutls_mpi_release (&X);
159 _gnutls_write_uint16 (n_X, &(*data)[0]);
161 /* calculate the key after calculating the message */
163 gnutls_calc_dh_key (session->key->client_Y, x, session->key->client_p);
165 if (session->key->KEY == NULL)
168 ret = GNUTLS_E_MEMORY_ERROR;
172 /* THESE SHOULD BE DISCARDED */
173 _gnutls_mpi_release (&session->key->client_Y);
174 _gnutls_mpi_release (&session->key->client_p);
175 _gnutls_mpi_release (&session->key->client_g);
177 if (_gnutls_cipher_suite_get_kx_algo
178 (&session->security_parameters.current_cipher_suite)
179 != GNUTLS_KX_DHE_PSK)
181 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
183 else /* In DHE_PSK the key is set differently */
185 gnutls_datum_t tmp_dh_key;
187 ret = _gnutls_mpi_dprint (session->key->KEY, &tmp_dh_key);
194 ret = _gnutls_set_psk_session_key (session, pskkey, &tmp_dh_key);
195 _gnutls_free_datum (&tmp_dh_key);
198 _gnutls_mpi_release (&session->key->KEY);
209 _gnutls_mpi_release (&x);
210 _gnutls_mpi_release (&X);
221 _gnutls_proc_dh_common_server_kx (gnutls_session_t session,
222 opaque * data, size_t _data_size, int psk)
224 uint16_t n_Y, n_g, n_p;
225 size_t _n_Y, _n_g, _n_p;
229 int i, bits, psk_size, ret;
230 ssize_t data_size = _data_size;
236 DECR_LEN (data_size, 2);
237 psk_size = _gnutls_read_uint16 (&data[i]);
238 DECR_LEN (data_size, psk_size);
242 DECR_LEN (data_size, 2);
243 n_p = _gnutls_read_uint16 (&data[i]);
246 DECR_LEN (data_size, n_p);
250 DECR_LEN (data_size, 2);
251 n_g = _gnutls_read_uint16 (&data[i]);
254 DECR_LEN (data_size, n_g);
258 DECR_LEN (data_size, 2);
259 n_Y = _gnutls_read_uint16 (&data[i]);
262 DECR_LEN (data_size, n_Y);
270 if (_gnutls_mpi_scan_nz (&session->key->client_Y, data_Y, _n_Y) != 0)
273 return GNUTLS_E_MPI_SCAN_FAILED;
276 if (_gnutls_mpi_scan_nz (&session->key->client_g, data_g, _n_g) != 0)
279 return GNUTLS_E_MPI_SCAN_FAILED;
281 if (_gnutls_mpi_scan_nz (&session->key->client_p, data_p, _n_p) != 0)
284 return GNUTLS_E_MPI_SCAN_FAILED;
287 bits = _gnutls_dh_get_allowed_prime_bits (session);
294 if (_gnutls_mpi_get_nbits (session->key->client_p) < (size_t) bits)
296 /* the prime used by the peer is not acceptable
299 return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
302 _gnutls_dh_set_group (session, session->key->client_g,
303 session->key->client_p);
304 _gnutls_dh_set_peer_public (session, session->key->client_Y);
306 ret = n_Y + n_p + n_g + 6;
313 /* If the psk flag is set, then an empty psk_identity_hint will
316 _gnutls_dh_common_print_server_kx (gnutls_session_t session,
317 bigint_t g, bigint_t p, opaque ** data,
321 size_t n_X, n_g, n_p;
322 int ret, data_size, pos;
325 X = gnutls_calc_dh_secret (&x, g, p);
326 if (X == NULL || x == NULL)
329 return GNUTLS_E_MEMORY_ERROR;
332 session->key->dh_secret = x;
333 _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));
335 _gnutls_mpi_print (g, NULL, &n_g);
336 _gnutls_mpi_print (p, NULL, &n_p);
337 _gnutls_mpi_print (X, NULL, &n_X);
339 data_size = n_g + n_p + n_X + 6;
343 (*data) = gnutls_malloc (data_size);
346 _gnutls_mpi_release (&X);
347 return GNUTLS_E_MEMORY_ERROR;
355 _gnutls_write_uint16 (0, &pdata[pos]);
359 _gnutls_mpi_print (p, &pdata[pos + 2], &n_p);
360 _gnutls_write_uint16 (n_p, &pdata[pos]);
364 _gnutls_mpi_print (g, &pdata[pos + 2], &n_g);
365 _gnutls_write_uint16 (n_g, &pdata[pos]);
369 _gnutls_mpi_print (X, &pdata[pos + 2], &n_X);
370 _gnutls_mpi_release (&X);
372 _gnutls_write_uint16 (n_X, &pdata[pos]);
374 /* do not use data_size. _gnutls_mpi_print() might
375 * have been pessimist and might have returned initially
377 ret = n_g + n_p + n_X + 6;