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 library 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
, &tmp_dh_key
);
109 _gnutls_free_datum (&tmp_dh_key
);
113 _gnutls_mpi_release (&session
->key
->KEY
);
124 _gnutls_gen_dh_common_client_kx (gnutls_session_t session
, opaque
** data
)
126 bigint_t x
= NULL
, X
= NULL
;
132 X
= gnutls_calc_dh_secret (&x
, session
->key
->client_g
,
133 session
->key
->client_p
);
134 if (X
== NULL
|| x
== NULL
)
137 ret
= GNUTLS_E_MEMORY_ERROR
;
141 _gnutls_dh_set_secret_bits (session
, _gnutls_mpi_get_nbits (x
));
143 _gnutls_mpi_print (X
, NULL
, &n_X
);
144 (*data
) = gnutls_malloc (n_X
+ 2);
147 ret
= GNUTLS_E_MEMORY_ERROR
;
151 _gnutls_mpi_print (X
, &(*data
)[2], &n_X
);
152 _gnutls_mpi_release (&X
);
154 _gnutls_write_uint16 (n_X
, &(*data
)[0]);
156 /* calculate the key after calculating the message */
158 gnutls_calc_dh_key (session
->key
->client_Y
, x
, session
->key
->client_p
);
160 _gnutls_mpi_release (&x
);
161 if (session
->key
->KEY
== NULL
)
164 ret
= GNUTLS_E_MEMORY_ERROR
;
168 /* THESE SHOULD BE DISCARDED */
169 _gnutls_mpi_release (&session
->key
->client_Y
);
170 _gnutls_mpi_release (&session
->key
->client_p
);
171 _gnutls_mpi_release (&session
->key
->client_g
);
173 if (_gnutls_cipher_suite_get_kx_algo
174 (&session
->security_parameters
.current_cipher_suite
)
175 != GNUTLS_KX_DHE_PSK
)
177 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &session
->key
->key
);
179 else /* In DHE_PSK the key is set differently */
181 gnutls_datum_t tmp_dh_key
;
182 ret
= _gnutls_mpi_dprint (session
->key
->KEY
, &tmp_dh_key
);
189 ret
= _gnutls_set_psk_session_key (session
, &tmp_dh_key
);
190 _gnutls_free_datum (&tmp_dh_key
);
194 _gnutls_mpi_release (&session
->key
->KEY
);
205 _gnutls_mpi_release (&x
);
206 _gnutls_mpi_release (&X
);
213 _gnutls_proc_dh_common_server_kx (gnutls_session_t session
,
214 opaque
* data
, size_t _data_size
, int psk
)
216 uint16_t n_Y
, n_g
, n_p
;
217 size_t _n_Y
, _n_g
, _n_p
;
221 int i
, bits
, psk_size
, ret
;
222 ssize_t data_size
= _data_size
;
228 DECR_LEN (data_size
, 2);
229 psk_size
= _gnutls_read_uint16 (&data
[i
]);
230 DECR_LEN (data_size
, psk_size
);
234 DECR_LEN (data_size
, 2);
235 n_p
= _gnutls_read_uint16 (&data
[i
]);
238 DECR_LEN (data_size
, n_p
);
242 DECR_LEN (data_size
, 2);
243 n_g
= _gnutls_read_uint16 (&data
[i
]);
246 DECR_LEN (data_size
, n_g
);
250 DECR_LEN (data_size
, 2);
251 n_Y
= _gnutls_read_uint16 (&data
[i
]);
254 DECR_LEN (data_size
, n_Y
);
262 if (_gnutls_mpi_scan_nz (&session
->key
->client_Y
, data_Y
, _n_Y
) != 0)
265 return GNUTLS_E_MPI_SCAN_FAILED
;
268 if (_gnutls_mpi_scan_nz (&session
->key
->client_g
, data_g
, _n_g
) != 0)
271 return GNUTLS_E_MPI_SCAN_FAILED
;
273 if (_gnutls_mpi_scan_nz (&session
->key
->client_p
, data_p
, _n_p
) != 0)
276 return GNUTLS_E_MPI_SCAN_FAILED
;
279 bits
= _gnutls_dh_get_allowed_prime_bits (session
);
286 if (_gnutls_mpi_get_nbits (session
->key
->client_p
) < (size_t) bits
)
288 /* the prime used by the peer is not acceptable
291 return GNUTLS_E_DH_PRIME_UNACCEPTABLE
;
294 _gnutls_dh_set_group (session
, session
->key
->client_g
,
295 session
->key
->client_p
);
296 _gnutls_dh_set_peer_public (session
, session
->key
->client_Y
);
298 ret
= n_Y
+ n_p
+ n_g
+ 6;
305 /* If the psk flag is set, then an empty psk_identity_hint will
308 _gnutls_dh_common_print_server_kx (gnutls_session_t session
,
309 bigint_t g
, bigint_t p
, opaque
** data
,
313 size_t n_X
, n_g
, n_p
;
314 int ret
, data_size
, pos
;
317 X
= gnutls_calc_dh_secret (&x
, g
, p
);
318 if (X
== NULL
|| x
== NULL
)
321 return GNUTLS_E_MEMORY_ERROR
;
324 session
->key
->dh_secret
= x
;
325 _gnutls_dh_set_secret_bits (session
, _gnutls_mpi_get_nbits (x
));
327 _gnutls_mpi_print (g
, NULL
, &n_g
);
328 _gnutls_mpi_print (p
, NULL
, &n_p
);
329 _gnutls_mpi_print (X
, NULL
, &n_X
);
331 data_size
= n_g
+ n_p
+ n_X
+ 6;
335 (*data
) = gnutls_malloc (data_size
);
338 _gnutls_mpi_release (&X
);
339 return GNUTLS_E_MEMORY_ERROR
;
347 _gnutls_write_uint16 (0, &pdata
[pos
]);
351 _gnutls_mpi_print (p
, &pdata
[pos
+ 2], &n_p
);
352 _gnutls_write_uint16 (n_p
, &pdata
[pos
]);
356 _gnutls_mpi_print (g
, &pdata
[pos
+ 2], &n_g
);
357 _gnutls_write_uint16 (n_g
, &pdata
[pos
]);
361 _gnutls_mpi_print (X
, &pdata
[pos
+ 2], &n_X
);
362 _gnutls_mpi_release (&X
);
364 _gnutls_write_uint16 (n_X
, &pdata
[pos
]);