2 * Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
27 * and Anonymous DH key exchange(DHA). These are used in the handshake
28 * procedure of the certificate and anoymous authentication.
31 #include "gnutls_int.h"
32 #include "gnutls_auth.h"
33 #include "gnutls_errors.h"
34 #include "gnutls_dh.h"
35 #include "gnutls_num.h"
36 #include "gnutls_sig.h"
37 #include <gnutls_datum.h>
38 #include <gnutls_x509.h>
39 #include <gnutls_state.h>
40 #include <auth_dh_common.h>
41 #include <gnutls_algorithms.h>
44 /* Frees the dh_info_st structure.
47 _gnutls_free_dh_info (dh_info_st
* dh
)
50 _gnutls_free_datum (&dh
->prime
);
51 _gnutls_free_datum (&dh
->generator
);
52 _gnutls_free_datum (&dh
->public_key
);
56 _gnutls_proc_dh_common_client_kx (gnutls_session_t session
,
57 opaque
* data
, size_t _data_size
,
58 bigint_t g
, bigint_t p
)
63 ssize_t data_size
= _data_size
;
66 DECR_LEN (data_size
, 2);
67 n_Y
= _gnutls_read_uint16 (&data
[0]);
70 DECR_LEN (data_size
, n_Y
);
71 if (_gnutls_mpi_scan_nz (&session
->key
->client_Y
, &data
[2], _n_Y
))
74 return GNUTLS_E_MPI_SCAN_FAILED
;
77 _gnutls_dh_set_peer_public (session
, session
->key
->client_Y
);
80 gnutls_calc_dh_key (session
->key
->client_Y
, session
->key
->dh_secret
, p
);
82 if (session
->key
->KEY
== NULL
)
85 return GNUTLS_E_MEMORY_ERROR
;
88 _gnutls_mpi_release (&session
->key
->client_Y
);
89 _gnutls_mpi_release (&session
->key
->dh_secret
);
92 if (_gnutls_cipher_suite_get_kx_algo
93 (&session
->security_parameters
.current_cipher_suite
)
96 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &session
->key
->key
);
98 else /* In DHE_PSK the key is set differently */
100 gnutls_datum_t tmp_dh_key
;
101 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &tmp_dh_key
);
108 ret
= _gnutls_set_psk_session_key (session
, NULL
, &tmp_dh_key
);
109 _gnutls_free_datum (&tmp_dh_key
);
113 _gnutls_mpi_release (&session
->key
->KEY
);
123 int _gnutls_gen_dh_common_client_kx (gnutls_session_t session
, opaque
** data
)
125 return _gnutls_gen_dh_common_client_kx_int(session
, data
, NULL
);
129 _gnutls_gen_dh_common_client_kx_int (gnutls_session_t session
, opaque
** data
, gnutls_datum_t
* pskkey
)
131 bigint_t x
= NULL
, X
= NULL
;
137 X
= gnutls_calc_dh_secret (&x
, session
->key
->client_g
,
138 session
->key
->client_p
);
139 if (X
== NULL
|| x
== NULL
)
142 ret
= GNUTLS_E_MEMORY_ERROR
;
146 _gnutls_dh_set_secret_bits (session
, _gnutls_mpi_get_nbits (x
));
148 _gnutls_mpi_print (X
, NULL
, &n_X
);
149 (*data
) = gnutls_malloc (n_X
+ 2);
152 ret
= GNUTLS_E_MEMORY_ERROR
;
156 _gnutls_mpi_print (X
, &(*data
)[2], &n_X
);
157 _gnutls_mpi_release (&X
);
159 _gnutls_write_uint16 (n_X
, &(*data
)[0]);
161 /* calculate the key after calculating the message */
163 gnutls_calc_dh_key (session
->key
->client_Y
, x
, session
->key
->client_p
);
165 if (session
->key
->KEY
== NULL
)
168 ret
= GNUTLS_E_MEMORY_ERROR
;
172 /* THESE SHOULD BE DISCARDED */
173 _gnutls_mpi_release (&session
->key
->client_Y
);
174 _gnutls_mpi_release (&session
->key
->client_p
);
175 _gnutls_mpi_release (&session
->key
->client_g
);
177 if (_gnutls_cipher_suite_get_kx_algo
178 (&session
->security_parameters
.current_cipher_suite
)
179 != GNUTLS_KX_DHE_PSK
)
181 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &session
->key
->key
);
183 else /* In DHE_PSK the key is set differently */
185 gnutls_datum_t tmp_dh_key
;
187 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &tmp_dh_key
);
194 ret
= _gnutls_set_psk_session_key (session
, pskkey
, &tmp_dh_key
);
195 _gnutls_free_datum (&tmp_dh_key
);
198 _gnutls_mpi_release (&session
->key
->KEY
);
209 _gnutls_mpi_release (&x
);
210 _gnutls_mpi_release (&X
);
217 _gnutls_proc_dh_common_server_kx (gnutls_session_t session
,
218 opaque
* data
, size_t _data_size
, int psk
)
220 uint16_t n_Y
, n_g
, n_p
;
221 size_t _n_Y
, _n_g
, _n_p
;
225 int i
, bits
, psk_size
, ret
;
226 ssize_t data_size
= _data_size
;
232 DECR_LEN (data_size
, 2);
233 psk_size
= _gnutls_read_uint16 (&data
[i
]);
234 DECR_LEN (data_size
, psk_size
);
238 DECR_LEN (data_size
, 2);
239 n_p
= _gnutls_read_uint16 (&data
[i
]);
242 DECR_LEN (data_size
, n_p
);
246 DECR_LEN (data_size
, 2);
247 n_g
= _gnutls_read_uint16 (&data
[i
]);
250 DECR_LEN (data_size
, n_g
);
254 DECR_LEN (data_size
, 2);
255 n_Y
= _gnutls_read_uint16 (&data
[i
]);
258 DECR_LEN (data_size
, n_Y
);
266 if (_gnutls_mpi_scan_nz (&session
->key
->client_Y
, data_Y
, _n_Y
) != 0)
269 return GNUTLS_E_MPI_SCAN_FAILED
;
272 if (_gnutls_mpi_scan_nz (&session
->key
->client_g
, data_g
, _n_g
) != 0)
275 return GNUTLS_E_MPI_SCAN_FAILED
;
277 if (_gnutls_mpi_scan_nz (&session
->key
->client_p
, data_p
, _n_p
) != 0)
280 return GNUTLS_E_MPI_SCAN_FAILED
;
283 bits
= _gnutls_dh_get_allowed_prime_bits (session
);
290 if (_gnutls_mpi_get_nbits (session
->key
->client_p
) < (size_t) bits
)
292 /* the prime used by the peer is not acceptable
295 return GNUTLS_E_DH_PRIME_UNACCEPTABLE
;
298 _gnutls_dh_set_group (session
, session
->key
->client_g
,
299 session
->key
->client_p
);
300 _gnutls_dh_set_peer_public (session
, session
->key
->client_Y
);
302 ret
= n_Y
+ n_p
+ n_g
+ 6;
309 /* If the psk flag is set, then an empty psk_identity_hint will
312 _gnutls_dh_common_print_server_kx (gnutls_session_t session
,
313 bigint_t g
, bigint_t p
, opaque
** data
,
317 size_t n_X
, n_g
, n_p
;
318 int ret
, data_size
, pos
;
321 X
= gnutls_calc_dh_secret (&x
, g
, p
);
322 if (X
== NULL
|| x
== NULL
)
325 return GNUTLS_E_MEMORY_ERROR
;
328 session
->key
->dh_secret
= x
;
329 _gnutls_dh_set_secret_bits (session
, _gnutls_mpi_get_nbits (x
));
331 _gnutls_mpi_print (g
, NULL
, &n_g
);
332 _gnutls_mpi_print (p
, NULL
, &n_p
);
333 _gnutls_mpi_print (X
, NULL
, &n_X
);
335 data_size
= n_g
+ n_p
+ n_X
+ 6;
339 (*data
) = gnutls_malloc (data_size
);
342 _gnutls_mpi_release (&X
);
343 return GNUTLS_E_MEMORY_ERROR
;
351 _gnutls_write_uint16 (0, &pdata
[pos
]);
355 _gnutls_mpi_print (p
, &pdata
[pos
+ 2], &n_p
);
356 _gnutls_write_uint16 (n_p
, &pdata
[pos
]);
360 _gnutls_mpi_print (g
, &pdata
[pos
+ 2], &n_g
);
361 _gnutls_write_uint16 (n_g
, &pdata
[pos
]);
365 _gnutls_mpi_print (X
, &pdata
[pos
+ 2], &n_X
);
366 _gnutls_mpi_release (&X
);
368 _gnutls_write_uint16 (n_X
, &pdata
[pos
]);
370 /* do not use data_size. _gnutls_mpi_print() might
371 * have been pessimist and might have returned initially
373 ret
= n_g
+ n_p
+ n_X
+ 6;