Improve.
[gnutls.git] / lib / auth_dhe.c
blobeca85b34faa6c7068a8d5e1ced197d27aa71851c
1 /*
2 * Copyright (C) 2000, 2001, 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,
21 * USA
25 /* This file contains everything for the Ephemeral Diffie-Hellman
26 * (DHE) key exchange. This is used in the handshake procedure of the
27 * certificate 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_algorithms.h>
38 #include <auth_cert.h>
39 #include <gnutls_x509.h>
40 #include <gnutls_state.h>
41 #include <auth_dh_common.h>
43 static int gen_dhe_server_kx (gnutls_session_t, opaque **);
44 static int proc_dhe_server_kx (gnutls_session_t, opaque *, size_t);
45 static int proc_dhe_client_kx (gnutls_session_t, opaque *, size_t);
47 const mod_auth_st dhe_rsa_auth_struct = {
48 "DHE_RSA",
49 _gnutls_gen_cert_server_certificate,
50 _gnutls_gen_cert_client_certificate,
51 gen_dhe_server_kx,
52 _gnutls_gen_dh_common_client_kx,
53 _gnutls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */
54 _gnutls_gen_cert_server_cert_req, /* server cert request */
56 _gnutls_proc_cert_server_certificate,
57 _gnutls_proc_cert_client_certificate,
58 proc_dhe_server_kx,
59 proc_dhe_client_kx,
60 _gnutls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */
61 _gnutls_proc_cert_cert_req /* proc server cert request */
64 const mod_auth_st dhe_dss_auth_struct = {
65 "DHE_DSS",
66 _gnutls_gen_cert_server_certificate,
67 _gnutls_gen_cert_client_certificate,
68 gen_dhe_server_kx,
69 _gnutls_gen_dh_common_client_kx,
70 _gnutls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */
71 _gnutls_gen_cert_server_cert_req, /* server cert request */
73 _gnutls_proc_cert_server_certificate,
74 _gnutls_proc_cert_client_certificate,
75 proc_dhe_server_kx,
76 proc_dhe_client_kx,
77 _gnutls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */
78 _gnutls_proc_cert_cert_req /* proc server cert request */
82 static int
83 gen_dhe_server_kx (gnutls_session_t session, opaque ** data)
85 bigint_t g, p;
86 const bigint_t *mpis;
87 int ret = 0, data_size;
88 gnutls_cert *apr_cert_list;
89 gnutls_privkey *apr_pkey;
90 int apr_cert_list_length;
91 gnutls_datum_t signature, ddata;
92 gnutls_certificate_credentials_t cred;
93 gnutls_dh_params_t dh_params;
94 gnutls_sign_algorithm_t sign_algo;
95 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
97 cred = (gnutls_certificate_credentials_t)
98 _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
99 if (cred == NULL)
101 gnutls_assert ();
102 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
105 /* find the appropriate certificate */
106 if ((ret =
107 _gnutls_get_selected_cert (session, &apr_cert_list,
108 &apr_cert_list_length, &apr_pkey)) < 0)
110 gnutls_assert ();
111 return ret;
114 dh_params =
115 _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
116 mpis = _gnutls_dh_params_to_mpi (dh_params);
117 if (mpis == NULL)
119 gnutls_assert ();
120 return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
123 p = mpis[0];
124 g = mpis[1];
126 if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
127 sizeof (cert_auth_info_st), 0)) < 0)
129 gnutls_assert ();
130 return ret;
133 _gnutls_dh_set_group (session, g, p);
135 ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0);
136 if (ret < 0)
138 gnutls_assert ();
139 return ret;
141 data_size = ret;
143 /* Generate the signature. */
145 ddata.data = *data;
146 ddata.size = data_size;
148 if (apr_cert_list_length > 0)
150 if ((ret =
151 _gnutls_handshake_sign_data (session, &apr_cert_list[0],
152 apr_pkey, &ddata, &signature,
153 &sign_algo)) < 0)
155 gnutls_assert ();
156 gnutls_free (*data);
157 return ret;
160 else
162 gnutls_assert ();
163 return data_size; /* do not put a signature - ILLEGAL! */
166 *data = gnutls_realloc_fast (*data, data_size + signature.size + 4);
167 if (*data == NULL)
169 _gnutls_free_datum (&signature);
170 gnutls_assert ();
171 return GNUTLS_E_MEMORY_ERROR;
174 if (_gnutls_version_has_selectable_sighash (ver))
176 sign_algorithm_st aid;
178 if (sign_algo == GNUTLS_SIGN_UNKNOWN)
180 _gnutls_free_datum (&signature);
181 gnutls_assert ();
182 return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
185 aid = _gnutls_sign_to_tls_aid (sign_algo);
186 (*data)[data_size++] = aid.hash_algorithm;
187 (*data)[data_size++] = aid.sign_algorithm;
190 _gnutls_write_datum16 (&(*data)[data_size], signature);
191 data_size += signature.size + 2;
193 _gnutls_free_datum (&signature);
195 return data_size;
198 static int
199 proc_dhe_server_kx (gnutls_session_t session, opaque * data,
200 size_t _data_size)
202 int sigsize;
203 opaque *sigdata;
204 gnutls_datum_t vparams, signature;
205 int ret;
206 cert_auth_info_t info = _gnutls_get_auth_info (session);
207 ssize_t data_size = _data_size;
208 gnutls_cert peer_cert;
209 gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
210 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
212 if (info == NULL || info->ncerts == 0)
214 gnutls_assert ();
215 /* we need this in order to get peer's certificate */
216 return GNUTLS_E_INTERNAL_ERROR;
219 ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0);
220 if (ret < 0)
222 gnutls_assert ();
223 return ret;
226 /* VERIFY SIGNATURE */
228 vparams.size = ret;
229 vparams.data = data;
231 sigdata = &data[vparams.size];
232 if (_gnutls_version_has_selectable_sighash (ver))
234 sign_algorithm_st aid;
236 DECR_LEN (data_size, 1);
237 aid.hash_algorithm = *sigdata++;
238 DECR_LEN (data_size, 1);
239 aid.sign_algorithm = *sigdata++;
240 sign_algo = _gnutls_tls_aid_to_sign (&aid);
241 if (sign_algo == GNUTLS_SIGN_UNKNOWN)
243 gnutls_assert ();
244 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
247 DECR_LEN (data_size, 2);
248 sigsize = _gnutls_read_uint16 (sigdata);
249 sigdata += 2;
251 DECR_LEN (data_size, sigsize);
252 signature.data = sigdata;
253 signature.size = sigsize;
255 if ((ret =
256 _gnutls_get_auth_info_gcert (&peer_cert,
257 session->security_parameters.cert_type,
258 info, CERT_NO_COPY)) < 0)
260 gnutls_assert ();
261 return ret;
264 ret =
265 _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature,
266 sign_algo);
268 _gnutls_gcert_deinit (&peer_cert);
269 if (ret < 0)
271 gnutls_assert ();
272 return ret;
275 return ret;
280 static int
281 proc_dhe_client_kx (gnutls_session_t session, opaque * data,
282 size_t _data_size)
284 gnutls_certificate_credentials_t cred;
285 int ret;
286 bigint_t p, g;
287 const bigint_t *mpis;
288 gnutls_dh_params_t dh_params;
290 cred = (gnutls_certificate_credentials_t)
291 _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
292 if (cred == NULL)
294 gnutls_assert ();
295 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
298 dh_params =
299 _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
300 mpis = _gnutls_dh_params_to_mpi (dh_params);
301 if (mpis == NULL)
303 gnutls_assert ();
304 return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
307 p = mpis[0];
308 g = mpis[1];
310 ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p);
312 return ret;