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 anonymous 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>
41 /* Frees the dh_info_st structure.
44 _gnutls_free_dh_info (dh_info_st
* dh
)
47 _gnutls_free_datum (&dh
->prime
);
48 _gnutls_free_datum (&dh
->generator
);
49 _gnutls_free_datum (&dh
->public_key
);
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
)
61 ssize_t data_size
= _data_size
;
64 DECR_LEN (data_size
, 2);
65 n_Y
= _gnutls_read_uint16 (&data
[0]);
68 DECR_LEN (data_size
, n_Y
);
69 if (_gnutls_mpi_scan_nz (&session
->key
.client_Y
, &data
[2], _n_Y
))
72 return GNUTLS_E_MPI_SCAN_FAILED
;
75 _gnutls_dh_set_peer_public (session
, session
->key
.client_Y
);
78 gnutls_calc_dh_key (&session
->key
.KEY
, session
->key
.client_Y
, session
->key
.dh_secret
, p
);
80 return gnutls_assert_val(ret
);
82 _gnutls_mpi_release (&session
->key
.client_Y
);
83 _gnutls_mpi_release (&session
->key
.dh_secret
);
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
);
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
);
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
;
126 ret
= gnutls_calc_dh_secret (&X
, &x
, session
->key
.client_g
,
127 session
->key
.client_p
, 0);
134 _gnutls_dh_set_secret_bits (session
, _gnutls_mpi_get_nbits (x
));
136 ret
= _gnutls_buffer_append_mpi( data
, 16, X
, 0);
143 /* calculate the key after calculating the message */
145 gnutls_calc_dh_key (&session
->key
.KEY
, session
->key
.client_Y
, x
, session
->key
.client_p
);
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
);
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
);
189 _gnutls_mpi_release (&x
);
190 _gnutls_mpi_release (&X
);
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
;
205 ssize_t data_size
= _data_size
;
209 DECR_LEN (data_size
, 2);
210 n_p
= _gnutls_read_uint16 (&data
[i
]);
213 DECR_LEN (data_size
, n_p
);
217 DECR_LEN (data_size
, 2);
218 n_g
= _gnutls_read_uint16 (&data
[i
]);
221 DECR_LEN (data_size
, n_g
);
225 DECR_LEN (data_size
, 2);
226 n_Y
= _gnutls_read_uint16 (&data
[i
]);
229 DECR_LEN (data_size
, n_Y
);
236 if (_gnutls_mpi_scan_nz (&session
->key
.client_Y
, data_Y
, _n_Y
) != 0)
239 return GNUTLS_E_MPI_SCAN_FAILED
;
242 if (_gnutls_mpi_scan_nz (&session
->key
.client_g
, data_g
, _n_g
) != 0)
245 return GNUTLS_E_MPI_SCAN_FAILED
;
247 if (_gnutls_mpi_scan_nz (&session
->key
.client_p
, data_p
, _n_p
) != 0)
250 return GNUTLS_E_MPI_SCAN_FAILED
;
253 bits
= _gnutls_dh_get_allowed_prime_bits (session
);
260 if (_gnutls_mpi_get_nbits (session
->key
.client_p
) < (size_t) bits
)
262 /* the prime used by the peer is not acceptable
265 return GNUTLS_E_DH_PRIME_UNACCEPTABLE
;
268 _gnutls_dh_set_group (session
, session
->key
.client_g
,
269 session
->key
.client_p
);
270 _gnutls_dh_set_peer_public (session
, session
->key
.client_Y
);
272 ret
= n_Y
+ n_p
+ n_g
+ 6;
278 _gnutls_dh_common_print_server_kx (gnutls_session_t session
,
279 bigint_t g
, bigint_t p
, unsigned int q_bits
,
280 gnutls_buffer_st
* data
)
286 ret
= gnutls_calc_dh_secret (&Y
, &x
, g
, p
, q_bits
);
293 session
->key
.dh_secret
= x
;
294 _gnutls_dh_set_secret_bits (session
, _gnutls_mpi_get_nbits (x
));
296 ret
= _gnutls_buffer_append_mpi(data
, 16, p
, 0);
303 ret
= _gnutls_buffer_append_mpi(data
, 16, g
, 0);
310 ret
= _gnutls_buffer_append_mpi(data
, 16, Y
, 0);
319 _gnutls_mpi_release (&Y
);