Correctly restore gnutls_record_recv() in DTLS mode if interrupted during the retrasm...
[gnutls.git] / lib / auth / dh_common.c
blobf4bba1ae7a7875b370894cee6e913d035c177455
1 /*
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS 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 3 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 License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
24 * and Anonymous DH key exchange(DHA). These are used in the handshake
25 * procedure of the certificate and anoymous authentication.
28 #include "gnutls_int.h"
29 #include "gnutls_auth.h"
30 #include "gnutls_errors.h"
31 #include "gnutls_dh.h"
32 #include "gnutls_num.h"
33 #include "gnutls_sig.h"
34 #include <gnutls_datum.h>
35 #include <gnutls_x509.h>
36 #include <gnutls_state.h>
37 #include <auth/dh_common.h>
38 #include <algorithms.h>
39 #include <auth/psk.h>
41 /* Frees the dh_info_st structure.
43 void
44 _gnutls_free_dh_info (dh_info_st * dh)
46 dh->secret_bits = 0;
47 _gnutls_free_datum (&dh->prime);
48 _gnutls_free_datum (&dh->generator);
49 _gnutls_free_datum (&dh->public_key);
52 int
53 _gnutls_proc_dh_common_client_kx (gnutls_session_t session,
54 uint8_t * data, size_t _data_size,
55 bigint_t g, bigint_t p,
56 gnutls_datum_t* psk_key)
58 uint16_t n_Y;
59 size_t _n_Y;
60 int ret;
61 ssize_t data_size = _data_size;
64 DECR_LEN (data_size, 2);
65 n_Y = _gnutls_read_uint16 (&data[0]);
66 _n_Y = n_Y;
68 DECR_LEN (data_size, n_Y);
69 if (_gnutls_mpi_scan_nz (&session->key->client_Y, &data[2], _n_Y))
71 gnutls_assert ();
72 return GNUTLS_E_MPI_SCAN_FAILED;
75 _gnutls_dh_set_peer_public (session, session->key->client_Y);
77 ret =
78 gnutls_calc_dh_key (&session->key->KEY, session->key->client_Y, session->key->dh_secret, p);
79 if (ret < 0)
80 return gnutls_assert_val(ret);
82 _gnutls_mpi_release (&session->key->client_Y);
83 _gnutls_mpi_release (&session->key->dh_secret);
86 if (psk_key == NULL)
88 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
90 else /* In DHE_PSK the key is set differently */
92 gnutls_datum_t tmp_dh_key;
93 ret = _gnutls_mpi_dprint (session->key->KEY, &tmp_dh_key);
94 if (ret < 0)
96 gnutls_assert ();
97 return ret;
100 ret = _gnutls_set_psk_session_key (session, psk_key, &tmp_dh_key);
101 _gnutls_free_datum (&tmp_dh_key);
105 _gnutls_mpi_release (&session->key->KEY);
107 if (ret < 0)
109 return ret;
112 return 0;
115 int _gnutls_gen_dh_common_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
117 return _gnutls_gen_dh_common_client_kx_int(session, data, NULL);
121 _gnutls_gen_dh_common_client_kx_int (gnutls_session_t session, gnutls_buffer_st* data, gnutls_datum_t* pskkey)
123 bigint_t x = NULL, X = NULL;
124 int ret;
126 ret = gnutls_calc_dh_secret (&X, &x, session->key->client_g,
127 session->key->client_p, 0);
128 if (ret < 0)
130 gnutls_assert ();
131 goto error;
134 _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));
136 ret = _gnutls_buffer_append_mpi( data, 16, X, 0);
137 if (ret < 0)
139 gnutls_assert();
140 goto error;
143 /* calculate the key after calculating the message */
144 ret =
145 gnutls_calc_dh_key (&session->key->KEY, session->key->client_Y, x, session->key->client_p);
146 if (ret < 0)
148 gnutls_assert();
149 goto error;
152 /* THESE SHOULD BE DISCARDED */
153 _gnutls_mpi_release (&session->key->client_Y);
154 _gnutls_mpi_release (&session->key->client_p);
155 _gnutls_mpi_release (&session->key->client_g);
157 if (_gnutls_cipher_suite_get_kx_algo
158 (session->security_parameters.cipher_suite)
159 != GNUTLS_KX_DHE_PSK)
161 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
163 else /* In DHE_PSK the key is set differently */
165 gnutls_datum_t tmp_dh_key;
167 ret = _gnutls_mpi_dprint (session->key->KEY, &tmp_dh_key);
168 if (ret < 0)
170 gnutls_assert ();
171 goto error;
174 ret = _gnutls_set_psk_session_key (session, pskkey, &tmp_dh_key);
175 _gnutls_free_datum (&tmp_dh_key);
178 _gnutls_mpi_release (&session->key->KEY);
180 if (ret < 0)
182 gnutls_assert ();
183 goto error;
186 ret = data->length;
188 error:
189 _gnutls_mpi_release (&x);
190 _gnutls_mpi_release (&X);
191 return ret;
194 /* Returns the bytes parsed */
196 _gnutls_proc_dh_common_server_kx (gnutls_session_t session,
197 uint8_t * data, size_t _data_size)
199 uint16_t n_Y, n_g, n_p;
200 size_t _n_Y, _n_g, _n_p;
201 uint8_t *data_p;
202 uint8_t *data_g;
203 uint8_t *data_Y;
204 int i, bits, ret;
205 ssize_t data_size = _data_size;
207 i = 0;
209 DECR_LEN (data_size, 2);
210 n_p = _gnutls_read_uint16 (&data[i]);
211 i += 2;
213 DECR_LEN (data_size, n_p);
214 data_p = &data[i];
215 i += n_p;
217 DECR_LEN (data_size, 2);
218 n_g = _gnutls_read_uint16 (&data[i]);
219 i += 2;
221 DECR_LEN (data_size, n_g);
222 data_g = &data[i];
223 i += n_g;
225 DECR_LEN (data_size, 2);
226 n_Y = _gnutls_read_uint16 (&data[i]);
227 i += 2;
229 DECR_LEN (data_size, n_Y);
230 data_Y = &data[i];
231 i += n_Y;
233 _n_Y = n_Y;
234 _n_g = n_g;
235 _n_p = n_p;
237 if (_gnutls_mpi_scan_nz (&session->key->client_Y, data_Y, _n_Y) != 0)
239 gnutls_assert ();
240 return GNUTLS_E_MPI_SCAN_FAILED;
243 if (_gnutls_mpi_scan_nz (&session->key->client_g, data_g, _n_g) != 0)
245 gnutls_assert ();
246 return GNUTLS_E_MPI_SCAN_FAILED;
248 if (_gnutls_mpi_scan_nz (&session->key->client_p, data_p, _n_p) != 0)
250 gnutls_assert ();
251 return GNUTLS_E_MPI_SCAN_FAILED;
254 bits = _gnutls_dh_get_allowed_prime_bits (session);
255 if (bits < 0)
257 gnutls_assert ();
258 return bits;
261 if (_gnutls_mpi_get_nbits (session->key->client_p) < (size_t) bits)
263 /* the prime used by the peer is not acceptable
265 gnutls_assert ();
266 return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
269 _gnutls_dh_set_group (session, session->key->client_g,
270 session->key->client_p);
271 _gnutls_dh_set_peer_public (session, session->key->client_Y);
273 ret = n_Y + n_p + n_g + 6;
275 return ret;
279 _gnutls_dh_common_print_server_kx (gnutls_session_t session,
280 bigint_t g, bigint_t p, unsigned int q_bits,
281 gnutls_buffer_st* data)
283 bigint_t x, Y;
284 int ret;
286 /* Y=g^x mod p */
287 ret = gnutls_calc_dh_secret (&Y, &x, g, p, q_bits);
288 if (ret < 0)
290 gnutls_assert ();
291 return ret;
294 session->key->dh_secret = x;
295 _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));
297 ret = _gnutls_buffer_append_mpi(data, 16, p, 0);
298 if (ret < 0)
300 ret = gnutls_assert_val(ret);
301 goto cleanup;
304 ret = _gnutls_buffer_append_mpi(data, 16, g, 0);
305 if (ret < 0)
307 ret = gnutls_assert_val(ret);
308 goto cleanup;
311 ret = _gnutls_buffer_append_mpi(data, 16, Y, 0);
312 if (ret < 0)
314 ret = gnutls_assert_val(ret);
315 goto cleanup;
318 cleanup:
319 _gnutls_mpi_release (&Y);
321 return data->length;