Verify callback is run in either side.
[gnutls.git] / lib / auth / dhe.c
blob26e0718a407c9194318d4d4570ea99b0af7d19ef
1 /*
2 * Copyright (C) 2000-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 everything for the Ephemeral Diffie-Hellman
24 * (DHE) key exchange. This is used in the handshake procedure of the
25 * certificate 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 <algorithms.h>
36 #include <auth/cert.h>
37 #include <gnutls_x509.h>
38 #include <gnutls_state.h>
39 #include <auth/dh_common.h>
40 #include <auth/ecdh_common.h>
42 static int gen_dhe_server_kx (gnutls_session_t, gnutls_buffer_st*);
43 static int proc_dhe_server_kx (gnutls_session_t, uint8_t *, size_t);
44 static int proc_dhe_client_kx (gnutls_session_t, uint8_t *, size_t);
46 const mod_auth_st ecdhe_ecdsa_auth_struct = {
47 "ECDHE_ECDSA",
48 _gnutls_gen_cert_server_crt,
49 _gnutls_gen_cert_client_crt,
50 gen_dhe_server_kx,
51 _gnutls_gen_ecdh_common_client_kx, /* This is the only difference */
52 _gnutls_gen_cert_client_crt_vrfy,
53 _gnutls_gen_cert_server_cert_req,
55 _gnutls_proc_crt,
56 _gnutls_proc_crt,
57 proc_dhe_server_kx,
58 proc_dhe_client_kx,
59 _gnutls_proc_cert_client_crt_vrfy,
60 _gnutls_proc_cert_cert_req
63 const mod_auth_st ecdhe_rsa_auth_struct = {
64 "ECDHE_RSA",
65 _gnutls_gen_cert_server_crt,
66 _gnutls_gen_cert_client_crt,
67 gen_dhe_server_kx,
68 _gnutls_gen_ecdh_common_client_kx, /* This is the only difference */
69 _gnutls_gen_cert_client_crt_vrfy,
70 _gnutls_gen_cert_server_cert_req,
72 _gnutls_proc_crt,
73 _gnutls_proc_crt,
74 proc_dhe_server_kx,
75 proc_dhe_client_kx,
76 _gnutls_proc_cert_client_crt_vrfy,
77 _gnutls_proc_cert_cert_req
80 const mod_auth_st dhe_rsa_auth_struct = {
81 "DHE_RSA",
82 _gnutls_gen_cert_server_crt,
83 _gnutls_gen_cert_client_crt,
84 gen_dhe_server_kx,
85 _gnutls_gen_dh_common_client_kx,
86 _gnutls_gen_cert_client_crt_vrfy, /* gen client cert vrfy */
87 _gnutls_gen_cert_server_cert_req, /* server cert request */
89 _gnutls_proc_crt,
90 _gnutls_proc_crt,
91 proc_dhe_server_kx,
92 proc_dhe_client_kx,
93 _gnutls_proc_cert_client_crt_vrfy, /* proc client cert vrfy */
94 _gnutls_proc_cert_cert_req /* proc server cert request */
97 const mod_auth_st dhe_dss_auth_struct = {
98 "DHE_DSS",
99 _gnutls_gen_cert_server_crt,
100 _gnutls_gen_cert_client_crt,
101 gen_dhe_server_kx,
102 _gnutls_gen_dh_common_client_kx,
103 _gnutls_gen_cert_client_crt_vrfy, /* gen client cert vrfy */
104 _gnutls_gen_cert_server_cert_req, /* server cert request */
106 _gnutls_proc_crt,
107 _gnutls_proc_crt,
108 proc_dhe_server_kx,
109 proc_dhe_client_kx,
110 _gnutls_proc_cert_client_crt_vrfy, /* proc client cert vrfy */
111 _gnutls_proc_cert_cert_req /* proc server cert request */
115 static int
116 gen_dhe_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
118 bigint_t g, p;
119 const bigint_t *mpis;
120 int ret = 0, data_size;
121 gnutls_pcert_st *apr_cert_list;
122 gnutls_privkey_t apr_pkey;
123 int apr_cert_list_length;
124 gnutls_datum_t signature = { NULL, 0 }, ddata;
125 gnutls_certificate_credentials_t cred;
126 gnutls_dh_params_t dh_params;
127 gnutls_sign_algorithm_t sign_algo;
128 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
130 cred = (gnutls_certificate_credentials_t)
131 _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
132 if (cred == NULL)
134 gnutls_assert ();
135 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
138 /* find the appropriate certificate */
139 if ((ret =
140 _gnutls_get_selected_cert (session, &apr_cert_list,
141 &apr_cert_list_length, &apr_pkey)) < 0)
143 gnutls_assert ();
144 return ret;
147 if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
148 sizeof (cert_auth_info_st), 0)) < 0)
150 gnutls_assert ();
151 return ret;
154 if (!_gnutls_session_is_ecc (session))
156 dh_params =
157 _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
158 mpis = _gnutls_dh_params_to_mpi (dh_params);
159 if (mpis == NULL)
161 gnutls_assert ();
162 return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
165 p = mpis[0];
166 g = mpis[1];
168 _gnutls_dh_set_group (session, g, p);
170 ret = _gnutls_dh_common_print_server_kx (session, g, p, dh_params->q_bits, data);
172 else
174 ret = _gnutls_ecdh_common_print_server_kx (session, data, _gnutls_session_ecc_curve_get(session));
177 if (ret < 0)
179 gnutls_assert ();
180 return ret;
182 data_size = ret;
184 /* Generate the signature. */
186 ddata.data = data->data;
187 ddata.size = data->length;
189 if (apr_cert_list_length > 0)
191 if ((ret =
192 _gnutls_handshake_sign_data (session, &apr_cert_list[0],
193 apr_pkey, &ddata, &signature,
194 &sign_algo)) < 0)
196 gnutls_assert ();
197 goto cleanup;
200 else
202 gnutls_assert ();
203 ret = data_size; /* do not put a signature - ILLEGAL! */
204 goto cleanup;
207 if (_gnutls_version_has_selectable_sighash (ver))
209 const sign_algorithm_st *aid;
210 uint8_t p[2];
212 if (sign_algo == GNUTLS_SIGN_UNKNOWN)
214 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
215 goto cleanup;
218 aid = _gnutls_sign_to_tls_aid (sign_algo);
219 if (aid == NULL)
221 gnutls_assert();
222 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
223 goto cleanup;
226 p[0] = aid->hash_algorithm;
227 p[1] = aid->sign_algorithm;
229 ret = _gnutls_buffer_append_data(data, p, 2);
230 if (ret < 0)
232 gnutls_assert();
233 goto cleanup;
237 ret = _gnutls_buffer_append_data_prefix(data, 16, signature.data, signature.size);
238 if (ret < 0)
240 gnutls_assert();
243 ret = data->length;
245 cleanup:
246 _gnutls_free_datum (&signature);
247 return ret;
251 static int
252 proc_dhe_server_kx (gnutls_session_t session, uint8_t * data,
253 size_t _data_size)
255 int sigsize;
256 uint8_t *sigdata;
257 gnutls_datum_t vparams, signature;
258 int ret;
259 cert_auth_info_t info = _gnutls_get_auth_info (session);
260 ssize_t data_size = _data_size;
261 gnutls_pcert_st peer_cert;
262 gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN;
263 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
265 if (info == NULL || info->ncerts == 0)
267 gnutls_assert ();
268 /* we need this in order to get peer's certificate */
269 return GNUTLS_E_INTERNAL_ERROR;
272 if (!_gnutls_session_is_ecc (session))
273 ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size);
274 else
275 ret = _gnutls_proc_ecdh_common_server_kx (session, data, _data_size);
277 if (ret < 0)
279 gnutls_assert ();
280 return ret;
283 /* VERIFY SIGNATURE */
285 vparams.size = ret;
286 vparams.data = data;
288 sigdata = &data[vparams.size];
289 if (_gnutls_version_has_selectable_sighash (ver))
291 sign_algorithm_st aid;
293 DECR_LEN (data_size, 1);
294 aid.hash_algorithm = *sigdata++;
295 DECR_LEN (data_size, 1);
296 aid.sign_algorithm = *sigdata++;
297 sign_algo = _gnutls_tls_aid_to_sign (&aid);
298 if (sign_algo == GNUTLS_SIGN_UNKNOWN)
300 _gnutls_debug_log("unknown signature %d.%d\n", aid.sign_algorithm, aid.hash_algorithm);
301 gnutls_assert ();
302 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
305 DECR_LEN (data_size, 2);
306 sigsize = _gnutls_read_uint16 (sigdata);
307 sigdata += 2;
309 DECR_LEN (data_size, sigsize);
310 signature.data = sigdata;
311 signature.size = sigsize;
313 if ((ret =
314 _gnutls_get_auth_info_pcert (&peer_cert,
315 session->security_parameters.cert_type,
316 info)) < 0)
318 gnutls_assert ();
319 return ret;
322 ret =
323 _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature,
324 sign_algo);
326 gnutls_pcert_deinit (&peer_cert);
327 if (ret < 0)
329 gnutls_assert ();
330 return ret;
333 return ret;
338 static int
339 proc_dhe_client_kx (gnutls_session_t session, uint8_t * data,
340 size_t _data_size)
342 gnutls_certificate_credentials_t cred;
343 int ret;
344 bigint_t p, g;
345 const bigint_t *mpis;
346 gnutls_dh_params_t dh_params;
348 cred = (gnutls_certificate_credentials_t)
349 _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
350 if (cred == NULL)
352 gnutls_assert ();
353 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
356 if (!_gnutls_session_is_ecc (session))
358 dh_params =
359 _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
360 mpis = _gnutls_dh_params_to_mpi (dh_params);
361 if (mpis == NULL)
362 return gnutls_assert_val(GNUTLS_E_NO_TEMPORARY_DH_PARAMS);
364 p = mpis[0];
365 g = mpis[1];
367 ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p, NULL);
369 else
370 ret = _gnutls_proc_ecdh_common_client_kx (session, data, _data_size,
371 _gnutls_session_ecc_curve_get(session), NULL);
373 return ret;