Fix memory leak.
[gnutls.git] / lib / auth_rsa_export.c
blob66826c98d184828f624fcac6d2d89416a0e250f8
1 /*
2 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 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 the RSA key exchange part of the certificate
26 * authentication.
29 #include "gnutls_int.h"
30 #include "gnutls_auth_int.h"
31 #include "gnutls_errors.h"
32 #include "gnutls_dh.h"
33 #include "gnutls_num.h"
34 #include "libtasn1.h"
35 #include "gnutls_datum.h"
36 #include "auth_cert.h"
37 #include <gnutls_pk.h>
38 #include <gnutls_algorithms.h>
39 #include <gnutls_global.h>
40 #include "debug.h"
41 #include <gnutls_sig.h>
42 #include <gnutls_x509.h>
43 #include <gnutls_rsa_export.h>
44 #include <gnutls_state.h>
46 int _gnutls_gen_rsa_client_kx (gnutls_session_t, opaque **);
47 int _gnutls_proc_rsa_client_kx (gnutls_session_t, opaque *, size_t);
48 static int gen_rsa_export_server_kx (gnutls_session_t, opaque **);
49 static int proc_rsa_export_server_kx (gnutls_session_t, opaque *, size_t);
51 const mod_auth_st rsa_export_auth_struct = {
52 "RSA EXPORT",
53 _gnutls_gen_cert_server_certificate,
54 _gnutls_gen_cert_client_certificate,
55 gen_rsa_export_server_kx,
56 _gnutls_gen_rsa_client_kx,
57 _gnutls_gen_cert_client_cert_vrfy, /* gen client cert vrfy */
58 _gnutls_gen_cert_server_cert_req, /* server cert request */
60 _gnutls_proc_cert_server_certificate,
61 _gnutls_proc_cert_client_certificate,
62 proc_rsa_export_server_kx,
63 _gnutls_proc_rsa_client_kx, /* proc client kx */
64 _gnutls_proc_cert_client_cert_vrfy, /* proc client cert vrfy */
65 _gnutls_proc_cert_cert_req /* proc server cert request */
68 static int
69 gen_rsa_export_server_kx (gnutls_session_t session, opaque ** data)
71 gnutls_rsa_params_t rsa_params;
72 const mpi_t *rsa_mpis;
73 size_t n_e, n_m;
74 uint8_t *data_e, *data_m;
75 int ret = 0, data_size;
76 gnutls_cert *apr_cert_list;
77 gnutls_privkey *apr_pkey;
78 int apr_cert_list_length;
79 gnutls_datum_t signature, ddata;
80 cert_auth_info_t info;
81 gnutls_certificate_credentials_t cred;
83 cred = (gnutls_certificate_credentials_t)
84 _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
85 if (cred == NULL)
87 gnutls_assert ();
88 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
91 /* find the appropriate certificate */
92 if ((ret =
93 _gnutls_get_selected_cert (session, &apr_cert_list,
94 &apr_cert_list_length, &apr_pkey)) < 0)
96 gnutls_assert ();
97 return ret;
100 /* abort sending this message if we have a certificate
101 * of 512 bits or less.
103 if (apr_pkey && _gnutls_mpi_get_nbits (apr_pkey->params[0]) <= 512)
105 gnutls_assert ();
106 return GNUTLS_E_INT_RET_0;
109 rsa_params =
110 _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func,
111 session);
112 rsa_mpis = _gnutls_rsa_params_to_mpi (rsa_params);
113 if (rsa_mpis == NULL)
115 gnutls_assert ();
116 return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
119 if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
120 sizeof (cert_auth_info_st), 0)) < 0)
122 gnutls_assert ();
123 return ret;
126 info = _gnutls_get_auth_info (session);
127 _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);
129 _gnutls_mpi_print (NULL, &n_m, rsa_mpis[0]);
130 _gnutls_mpi_print (NULL, &n_e, rsa_mpis[1]);
132 (*data) = gnutls_malloc (n_e + n_m + 4);
133 if (*data == NULL)
135 return GNUTLS_E_MEMORY_ERROR;
138 data_m = &(*data)[0];
139 _gnutls_mpi_print (&data_m[2], &n_m, rsa_mpis[0]);
141 _gnutls_write_uint16 (n_m, data_m);
143 data_e = &data_m[2 + n_m];
144 _gnutls_mpi_print (&data_e[2], &n_e, rsa_mpis[1]);
146 _gnutls_write_uint16 (n_e, data_e);
148 data_size = n_m + n_e + 4;
151 /* Generate the signature. */
153 ddata.data = *data;
154 ddata.size = data_size;
156 if (apr_cert_list_length > 0)
158 if ((ret =
159 _gnutls_tls_sign_params (session, &apr_cert_list[0],
160 apr_pkey, &ddata, &signature)) < 0)
162 gnutls_assert ();
163 gnutls_free (*data);
164 *data = NULL;
165 return ret;
168 else
170 gnutls_assert ();
171 return data_size; /* do not put a signature - ILLEGAL! */
174 *data = gnutls_realloc_fast (*data, data_size + signature.size + 2);
175 if (*data == NULL)
177 _gnutls_free_datum (&signature);
178 gnutls_assert ();
179 return GNUTLS_E_MEMORY_ERROR;
182 _gnutls_write_datum16 (&((*data)[data_size]), signature);
183 data_size += signature.size + 2;
185 _gnutls_free_datum (&signature);
187 return data_size;
190 /* if the peer's certificate is of 512 bits or less, returns non zero.
193 _gnutls_peers_cert_less_512 (gnutls_session_t session)
195 gnutls_cert peer_cert;
196 int ret;
197 cert_auth_info_t info = _gnutls_get_auth_info (session);
199 if (info == NULL || info->ncerts == 0)
201 gnutls_assert ();
202 /* we need this in order to get peer's certificate */
203 return 0;
206 if ((ret =
207 _gnutls_get_auth_info_gcert (&peer_cert,
208 session->security_parameters.cert_type,
209 info, CERT_NO_COPY)) < 0)
211 gnutls_assert ();
212 return 0;
215 if (peer_cert.subject_pk_algorithm != GNUTLS_PK_RSA)
217 gnutls_assert ();
218 _gnutls_gcert_deinit (&peer_cert);
219 return 0;
222 if (_gnutls_mpi_get_nbits (peer_cert.params[0]) <= 512)
224 _gnutls_gcert_deinit (&peer_cert);
225 return 1;
228 _gnutls_gcert_deinit (&peer_cert);
230 return 0;
233 static int
234 proc_rsa_export_server_kx (gnutls_session_t session,
235 opaque * data, size_t _data_size)
237 uint16_t n_m, n_e;
238 size_t _n_m, _n_e;
239 uint8_t *data_m;
240 uint8_t *data_e;
241 int i, sigsize;
242 gnutls_datum_t vparams, signature;
243 int ret;
244 ssize_t data_size = _data_size;
245 cert_auth_info_t info;
246 gnutls_cert peer_cert;
248 info = _gnutls_get_auth_info (session);
249 if (info == NULL || info->ncerts == 0)
251 gnutls_assert ();
252 /* we need this in order to get peer's certificate */
253 return GNUTLS_E_INTERNAL_ERROR;
257 i = 0;
259 DECR_LEN (data_size, 2);
260 n_m = _gnutls_read_uint16 (&data[i]);
261 i += 2;
263 DECR_LEN (data_size, n_m);
264 data_m = &data[i];
265 i += n_m;
267 DECR_LEN (data_size, 2);
268 n_e = _gnutls_read_uint16 (&data[i]);
269 i += 2;
271 DECR_LEN (data_size, n_e);
272 data_e = &data[i];
273 i += n_e;
275 _n_e = n_e;
276 _n_m = n_m;
278 if (_gnutls_mpi_scan_nz (&session->key->rsa[0], data_m, &_n_m) != 0)
280 gnutls_assert ();
281 return GNUTLS_E_MPI_SCAN_FAILED;
284 if (_gnutls_mpi_scan_nz (&session->key->rsa[1], data_e, &_n_e) != 0)
286 gnutls_assert ();
287 return GNUTLS_E_MPI_SCAN_FAILED;
290 _gnutls_rsa_export_set_pubkey (session, session->key->rsa[1],
291 session->key->rsa[0]);
293 /* VERIFY SIGNATURE */
295 vparams.size = n_m + n_e + 4;
296 vparams.data = data;
298 DECR_LEN (data_size, 2);
299 sigsize = _gnutls_read_uint16 (&data[vparams.size]);
301 DECR_LEN (data_size, sigsize);
302 signature.data = &data[vparams.size + 2];
303 signature.size = sigsize;
305 if ((ret =
306 _gnutls_get_auth_info_gcert (&peer_cert,
307 session->security_parameters.cert_type,
308 info, CERT_NO_COPY)) < 0)
310 gnutls_assert ();
311 return ret;
314 ret = _gnutls_verify_sig_params (session, &peer_cert, &vparams, &signature);
316 _gnutls_gcert_deinit (&peer_cert);
317 if (ret < 0)
319 gnutls_assert ();
322 return ret;