Sync with TP.
[gnutls.git] / lib / auth_dh_common.c
blob0e4b3ce442ca934605bc296af54b6977642689f7
1 /*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009 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 /* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
26 * and Anonymous DH key exchange(DHA). These are used in the handshake
27 * procedure of the certificate and anoymous authentication.
30 #include "gnutls_int.h"
31 #include "gnutls_auth.h"
32 #include "gnutls_errors.h"
33 #include "gnutls_dh.h"
34 #include "gnutls_num.h"
35 #include "gnutls_sig.h"
36 #include <gnutls_datum.h>
37 #include <gnutls_x509.h>
38 #include <gnutls_state.h>
39 #include <auth_dh_common.h>
40 #include <gnutls_algorithms.h>
41 #include <auth_psk.h>
43 /* Frees the dh_info_st structure.
45 void
46 _gnutls_free_dh_info (dh_info_st * dh)
48 dh->secret_bits = 0;
49 _gnutls_free_datum (&dh->prime);
50 _gnutls_free_datum (&dh->generator);
51 _gnutls_free_datum (&dh->public_key);
54 int
55 _gnutls_proc_dh_common_client_kx (gnutls_session_t session,
56 opaque * data, size_t _data_size,
57 bigint_t g, bigint_t p)
59 uint16_t n_Y;
60 size_t _n_Y;
61 int ret;
62 ssize_t data_size = _data_size;
65 DECR_LEN (data_size, 2);
66 n_Y = _gnutls_read_uint16 (&data[0]);
67 _n_Y = n_Y;
69 DECR_LEN (data_size, n_Y);
70 if (_gnutls_mpi_scan_nz (&session->key->client_Y, &data[2], _n_Y))
72 gnutls_assert ();
73 return GNUTLS_E_MPI_SCAN_FAILED;
76 _gnutls_dh_set_peer_public (session, session->key->client_Y);
78 session->key->KEY =
79 gnutls_calc_dh_key (session->key->client_Y, session->key->dh_secret, p);
81 if (session->key->KEY == NULL)
83 gnutls_assert ();
84 return GNUTLS_E_MEMORY_ERROR;
87 _gnutls_mpi_release (&session->key->client_Y);
88 _gnutls_mpi_release (&session->key->dh_secret);
91 if (_gnutls_cipher_suite_get_kx_algo
92 (&session->security_parameters.current_cipher_suite)
93 != GNUTLS_KX_DHE_PSK)
95 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
97 else /* In DHE_PSK the key is set differently */
99 gnutls_datum_t tmp_dh_key;
100 ret = _gnutls_mpi_dprint (session->key->KEY, &tmp_dh_key);
101 if (ret < 0)
103 gnutls_assert ();
104 return ret;
107 ret = _gnutls_set_psk_session_key (session, &tmp_dh_key);
108 _gnutls_free_datum (&tmp_dh_key);
112 _gnutls_mpi_release (&session->key->KEY);
114 if (ret < 0)
116 return ret;
119 return 0;
123 _gnutls_gen_dh_common_client_kx (gnutls_session_t session, opaque ** data)
125 bigint_t x = NULL, X = NULL;
126 size_t n_X;
127 int ret;
129 *data = NULL;
131 X = gnutls_calc_dh_secret (&x, session->key->client_g,
132 session->key->client_p);
133 if (X == NULL || x == NULL)
135 gnutls_assert ();
136 ret = GNUTLS_E_MEMORY_ERROR;
137 goto error;
140 _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));
142 _gnutls_mpi_print (X, NULL, &n_X);
143 (*data) = gnutls_malloc (n_X + 2);
144 if (*data == NULL)
146 ret = GNUTLS_E_MEMORY_ERROR;
147 goto error;
150 _gnutls_mpi_print (X, &(*data)[2], &n_X);
151 _gnutls_mpi_release (&X);
153 _gnutls_write_uint16 (n_X, &(*data)[0]);
155 /* calculate the key after calculating the message */
156 session->key->KEY =
157 gnutls_calc_dh_key (session->key->client_Y, x, session->key->client_p);
159 _gnutls_mpi_release (&x);
160 if (session->key->KEY == NULL)
162 gnutls_assert ();
163 ret = GNUTLS_E_MEMORY_ERROR;
164 goto error;
167 /* THESE SHOULD BE DISCARDED */
168 _gnutls_mpi_release (&session->key->client_Y);
169 _gnutls_mpi_release (&session->key->client_p);
170 _gnutls_mpi_release (&session->key->client_g);
172 if (_gnutls_cipher_suite_get_kx_algo
173 (&session->security_parameters.current_cipher_suite)
174 != GNUTLS_KX_DHE_PSK)
176 ret = _gnutls_mpi_dprint (session->key->KEY, &session->key->key);
178 else /* In DHE_PSK the key is set differently */
180 gnutls_datum_t tmp_dh_key;
181 ret = _gnutls_mpi_dprint (session->key->KEY, &tmp_dh_key);
182 if (ret < 0)
184 gnutls_assert ();
185 goto error;
188 ret = _gnutls_set_psk_session_key (session, &tmp_dh_key);
189 _gnutls_free_datum (&tmp_dh_key);
193 _gnutls_mpi_release (&session->key->KEY);
195 if (ret < 0)
197 gnutls_assert ();
198 goto error;
201 return n_X + 2;
203 error:
204 _gnutls_mpi_release (&x);
205 _gnutls_mpi_release (&X);
206 gnutls_free (*data);
207 *data = NULL;
208 return ret;
212 _gnutls_proc_dh_common_server_kx (gnutls_session_t session,
213 opaque * data, size_t _data_size, int psk)
215 uint16_t n_Y, n_g, n_p;
216 size_t _n_Y, _n_g, _n_p;
217 uint8_t *data_p;
218 uint8_t *data_g;
219 uint8_t *data_Y;
220 int i, bits, psk_size, ret;
221 ssize_t data_size = _data_size;
223 i = 0;
225 if (psk != 0)
227 DECR_LEN (data_size, 2);
228 psk_size = _gnutls_read_uint16 (&data[i]);
229 DECR_LEN (data_size, psk_size);
230 i += 2 + psk_size;
233 DECR_LEN (data_size, 2);
234 n_p = _gnutls_read_uint16 (&data[i]);
235 i += 2;
237 DECR_LEN (data_size, n_p);
238 data_p = &data[i];
239 i += n_p;
241 DECR_LEN (data_size, 2);
242 n_g = _gnutls_read_uint16 (&data[i]);
243 i += 2;
245 DECR_LEN (data_size, n_g);
246 data_g = &data[i];
247 i += n_g;
249 DECR_LEN (data_size, 2);
250 n_Y = _gnutls_read_uint16 (&data[i]);
251 i += 2;
253 DECR_LEN (data_size, n_Y);
254 data_Y = &data[i];
255 i += n_Y;
257 _n_Y = n_Y;
258 _n_g = n_g;
259 _n_p = n_p;
261 if (_gnutls_mpi_scan_nz (&session->key->client_Y, data_Y, _n_Y) != 0)
263 gnutls_assert ();
264 return GNUTLS_E_MPI_SCAN_FAILED;
267 if (_gnutls_mpi_scan_nz (&session->key->client_g, data_g, _n_g) != 0)
269 gnutls_assert ();
270 return GNUTLS_E_MPI_SCAN_FAILED;
272 if (_gnutls_mpi_scan_nz (&session->key->client_p, data_p, _n_p) != 0)
274 gnutls_assert ();
275 return GNUTLS_E_MPI_SCAN_FAILED;
278 bits = _gnutls_dh_get_allowed_prime_bits (session);
279 if (bits < 0)
281 gnutls_assert ();
282 return bits;
285 if (_gnutls_mpi_get_nbits (session->key->client_p) < (size_t) bits)
287 /* the prime used by the peer is not acceptable
289 gnutls_assert ();
290 return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
293 _gnutls_dh_set_group (session, session->key->client_g,
294 session->key->client_p);
295 _gnutls_dh_set_peer_public (session, session->key->client_Y);
297 ret = n_Y + n_p + n_g + 6;
298 if (psk != 0)
299 ret += 2;
301 return ret;
304 /* If the psk flag is set, then an empty psk_identity_hint will
305 * be inserted */
307 _gnutls_dh_common_print_server_kx (gnutls_session_t session,
308 bigint_t g, bigint_t p, opaque ** data,
309 int psk)
311 bigint_t x, X;
312 size_t n_X, n_g, n_p;
313 int ret, data_size, pos;
314 uint8_t *pdata;
316 X = gnutls_calc_dh_secret (&x, g, p);
317 if (X == NULL || x == NULL)
319 gnutls_assert ();
320 return GNUTLS_E_MEMORY_ERROR;
323 session->key->dh_secret = x;
324 _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x));
326 _gnutls_mpi_print (g, NULL, &n_g);
327 _gnutls_mpi_print (p, NULL, &n_p);
328 _gnutls_mpi_print (X, NULL, &n_X);
330 data_size = n_g + n_p + n_X + 6;
331 if (psk != 0)
332 data_size += 2;
334 (*data) = gnutls_malloc (data_size);
335 if (*data == NULL)
337 _gnutls_mpi_release (&X);
338 return GNUTLS_E_MEMORY_ERROR;
341 pos = 0;
342 pdata = *data;
344 if (psk != 0)
346 _gnutls_write_uint16 (0, &pdata[pos]);
347 pos += 2;
350 _gnutls_mpi_print (p, &pdata[pos + 2], &n_p);
351 _gnutls_write_uint16 (n_p, &pdata[pos]);
353 pos += n_p + 2;
355 _gnutls_mpi_print (g, &pdata[pos + 2], &n_g);
356 _gnutls_write_uint16 (n_g, &pdata[pos]);
358 pos += n_g + 2;
360 _gnutls_mpi_print (X, &pdata[pos + 2], &n_X);
361 _gnutls_mpi_release (&X);
363 _gnutls_write_uint16 (n_X, &pdata[pos]);
365 ret = data_size;
367 return ret;