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>
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
->client_Y
, session
->key
->dh_secret
, p
);
80 if (session
->key
->KEY
== NULL
)
83 return GNUTLS_E_MEMORY_ERROR
;
86 _gnutls_mpi_release (&session
->key
->client_Y
);
87 _gnutls_mpi_release (&session
->key
->dh_secret
);
92 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &session
->key
->key
);
94 else /* In DHE_PSK the key is set differently */
96 gnutls_datum_t tmp_dh_key
;
97 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &tmp_dh_key
);
104 ret
= _gnutls_set_psk_session_key (session
, psk_key
, &tmp_dh_key
);
105 _gnutls_free_datum (&tmp_dh_key
);
109 _gnutls_mpi_release (&session
->key
->KEY
);
119 int _gnutls_gen_dh_common_client_kx (gnutls_session_t session
, gnutls_buffer_st
* data
)
121 return _gnutls_gen_dh_common_client_kx_int(session
, data
, NULL
);
125 _gnutls_gen_dh_common_client_kx_int (gnutls_session_t session
, gnutls_buffer_st
* data
, gnutls_datum_t
* pskkey
)
127 bigint_t x
= NULL
, X
= NULL
;
130 X
= gnutls_calc_dh_secret (&x
, session
->key
->client_g
,
131 session
->key
->client_p
, 0);
132 if (X
== NULL
|| x
== NULL
)
135 ret
= GNUTLS_E_MEMORY_ERROR
;
139 _gnutls_dh_set_secret_bits (session
, _gnutls_mpi_get_nbits (x
));
141 ret
= _gnutls_buffer_append_mpi( data
, 16, X
, 0);
148 /* calculate the key after calculating the message */
150 gnutls_calc_dh_key (session
->key
->client_Y
, x
, session
->key
->client_p
);
152 if (session
->key
->KEY
== NULL
)
155 ret
= GNUTLS_E_MEMORY_ERROR
;
159 /* THESE SHOULD BE DISCARDED */
160 _gnutls_mpi_release (&session
->key
->client_Y
);
161 _gnutls_mpi_release (&session
->key
->client_p
);
162 _gnutls_mpi_release (&session
->key
->client_g
);
164 if (_gnutls_cipher_suite_get_kx_algo
165 (session
->security_parameters
.cipher_suite
)
166 != GNUTLS_KX_DHE_PSK
)
168 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &session
->key
->key
);
170 else /* In DHE_PSK the key is set differently */
172 gnutls_datum_t tmp_dh_key
;
174 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &tmp_dh_key
);
181 ret
= _gnutls_set_psk_session_key (session
, pskkey
, &tmp_dh_key
);
182 _gnutls_free_datum (&tmp_dh_key
);
185 _gnutls_mpi_release (&session
->key
->KEY
);
196 _gnutls_mpi_release (&x
);
197 _gnutls_mpi_release (&X
);
201 /* Returns the bytes parsed */
203 _gnutls_proc_dh_common_server_kx (gnutls_session_t session
,
204 uint8_t * data
, size_t _data_size
)
206 uint16_t n_Y
, n_g
, n_p
;
207 size_t _n_Y
, _n_g
, _n_p
;
212 ssize_t data_size
= _data_size
;
216 DECR_LEN (data_size
, 2);
217 n_p
= _gnutls_read_uint16 (&data
[i
]);
220 DECR_LEN (data_size
, n_p
);
224 DECR_LEN (data_size
, 2);
225 n_g
= _gnutls_read_uint16 (&data
[i
]);
228 DECR_LEN (data_size
, n_g
);
232 DECR_LEN (data_size
, 2);
233 n_Y
= _gnutls_read_uint16 (&data
[i
]);
236 DECR_LEN (data_size
, n_Y
);
244 if (_gnutls_mpi_scan_nz (&session
->key
->client_Y
, data_Y
, _n_Y
) != 0)
247 return GNUTLS_E_MPI_SCAN_FAILED
;
250 if (_gnutls_mpi_scan_nz (&session
->key
->client_g
, data_g
, _n_g
) != 0)
253 return GNUTLS_E_MPI_SCAN_FAILED
;
255 if (_gnutls_mpi_scan_nz (&session
->key
->client_p
, data_p
, _n_p
) != 0)
258 return GNUTLS_E_MPI_SCAN_FAILED
;
261 bits
= _gnutls_dh_get_allowed_prime_bits (session
);
268 if (_gnutls_mpi_get_nbits (session
->key
->client_p
) < (size_t) bits
)
270 /* the prime used by the peer is not acceptable
273 return GNUTLS_E_DH_PRIME_UNACCEPTABLE
;
276 _gnutls_dh_set_group (session
, session
->key
->client_g
,
277 session
->key
->client_p
);
278 _gnutls_dh_set_peer_public (session
, session
->key
->client_Y
);
280 ret
= n_Y
+ n_p
+ n_g
+ 6;
286 _gnutls_dh_common_print_server_kx (gnutls_session_t session
,
287 bigint_t g
, bigint_t p
, unsigned int q_bits
,
288 gnutls_buffer_st
* data
)
294 Y
= gnutls_calc_dh_secret (&x
, g
, p
, q_bits
);
295 if (Y
== NULL
|| x
== NULL
)
298 return GNUTLS_E_MEMORY_ERROR
;
301 session
->key
->dh_secret
= x
;
302 _gnutls_dh_set_secret_bits (session
, _gnutls_mpi_get_nbits (x
));
304 ret
= _gnutls_buffer_append_mpi(data
, 16, p
, 0);
307 ret
= gnutls_assert_val(ret
);
311 ret
= _gnutls_buffer_append_mpi(data
, 16, g
, 0);
314 ret
= gnutls_assert_val(ret
);
318 ret
= _gnutls_buffer_append_mpi(data
, 16, Y
, 0);
321 ret
= gnutls_assert_val(ret
);
326 _gnutls_mpi_release (&Y
);