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,
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>
43 /* Frees the dh_info_st structure.
46 _gnutls_free_dh_info (dh_info_st
* dh
)
49 _gnutls_free_datum (&dh
->prime
);
50 _gnutls_free_datum (&dh
->generator
);
51 _gnutls_free_datum (&dh
->public_key
);
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
)
62 ssize_t data_size
= _data_size
;
65 DECR_LEN (data_size
, 2);
66 n_Y
= _gnutls_read_uint16 (&data
[0]);
69 DECR_LEN (data_size
, n_Y
);
70 if (_gnutls_mpi_scan_nz (&session
->key
->client_Y
, &data
[2], _n_Y
))
73 return GNUTLS_E_MPI_SCAN_FAILED
;
76 _gnutls_dh_set_peer_public (session
, session
->key
->client_Y
);
79 gnutls_calc_dh_key (session
->key
->client_Y
, session
->key
->dh_secret
, p
);
81 if (session
->key
->KEY
== NULL
)
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
)
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
);
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
);
123 _gnutls_gen_dh_common_client_kx (gnutls_session_t session
, opaque
** data
)
125 bigint_t x
= NULL
, X
= NULL
;
131 X
= gnutls_calc_dh_secret (&x
, session
->key
->client_g
,
132 session
->key
->client_p
);
133 if (X
== NULL
|| x
== NULL
)
136 ret
= GNUTLS_E_MEMORY_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);
146 ret
= GNUTLS_E_MEMORY_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 */
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
)
163 ret
= GNUTLS_E_MEMORY_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
);
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
);
204 _gnutls_mpi_release (&x
);
205 _gnutls_mpi_release (&X
);
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
;
220 int i
, bits
, psk_size
, ret
;
221 ssize_t data_size
= _data_size
;
227 DECR_LEN (data_size
, 2);
228 psk_size
= _gnutls_read_uint16 (&data
[i
]);
229 DECR_LEN (data_size
, psk_size
);
233 DECR_LEN (data_size
, 2);
234 n_p
= _gnutls_read_uint16 (&data
[i
]);
237 DECR_LEN (data_size
, n_p
);
241 DECR_LEN (data_size
, 2);
242 n_g
= _gnutls_read_uint16 (&data
[i
]);
245 DECR_LEN (data_size
, n_g
);
249 DECR_LEN (data_size
, 2);
250 n_Y
= _gnutls_read_uint16 (&data
[i
]);
253 DECR_LEN (data_size
, n_Y
);
261 if (_gnutls_mpi_scan_nz (&session
->key
->client_Y
, data_Y
, _n_Y
) != 0)
264 return GNUTLS_E_MPI_SCAN_FAILED
;
267 if (_gnutls_mpi_scan_nz (&session
->key
->client_g
, data_g
, _n_g
) != 0)
270 return GNUTLS_E_MPI_SCAN_FAILED
;
272 if (_gnutls_mpi_scan_nz (&session
->key
->client_p
, data_p
, _n_p
) != 0)
275 return GNUTLS_E_MPI_SCAN_FAILED
;
278 bits
= _gnutls_dh_get_allowed_prime_bits (session
);
285 if (_gnutls_mpi_get_nbits (session
->key
->client_p
) < (size_t) bits
)
287 /* the prime used by the peer is not acceptable
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;
304 /* If the psk flag is set, then an empty psk_identity_hint will
307 _gnutls_dh_common_print_server_kx (gnutls_session_t session
,
308 bigint_t g
, bigint_t p
, opaque
** data
,
312 size_t n_X
, n_g
, n_p
;
313 int ret
, data_size
, pos
;
316 X
= gnutls_calc_dh_secret (&x
, g
, p
);
317 if (X
== NULL
|| x
== NULL
)
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;
334 (*data
) = gnutls_malloc (data_size
);
337 _gnutls_mpi_release (&X
);
338 return GNUTLS_E_MEMORY_ERROR
;
346 _gnutls_write_uint16 (0, &pdata
[pos
]);
350 _gnutls_mpi_print (p
, &pdata
[pos
+ 2], &n_p
);
351 _gnutls_write_uint16 (n_p
, &pdata
[pos
]);
355 _gnutls_mpi_print (g
, &pdata
[pos
+ 2], &n_g
);
356 _gnutls_write_uint16 (n_g
, &pdata
[pos
]);
360 _gnutls_mpi_print (X
, &pdata
[pos
+ 2], &n_X
);
361 _gnutls_mpi_release (&X
);
363 _gnutls_write_uint16 (n_X
, &pdata
[pos
]);