GNUTLS_E_ENCRYPTED_STRUCTURE is no more.
[gnutls.git] / lib / auth / rsa.c
blobf728503b89f57d1e5247db4619bbb8582c1a377c
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 the RSA key exchange part of the certificate
24 * authentication.
27 #include "gnutls_int.h"
28 #include "gnutls_auth.h"
29 #include "gnutls_errors.h"
30 #include "gnutls_dh.h"
31 #include "gnutls_num.h"
32 #include "gnutls_datum.h"
33 #include <auth/cert.h>
34 #include <gnutls_pk.h>
35 #include <algorithms.h>
36 #include <gnutls_global.h>
37 #include "debug.h"
38 #include <gnutls_sig.h>
39 #include <gnutls_x509.h>
40 #include <random.h>
41 #include <gnutls_mpi.h>
42 #include <abstract_int.h>
44 int _gnutls_gen_rsa_client_kx (gnutls_session_t, gnutls_buffer_st*);
45 static int proc_rsa_client_kx (gnutls_session_t, uint8_t *, size_t);
47 const mod_auth_st rsa_auth_struct = {
48 "RSA",
49 _gnutls_gen_cert_server_crt,
50 _gnutls_gen_cert_client_crt,
51 NULL, /* gen server kx */
52 _gnutls_gen_rsa_client_kx,
53 _gnutls_gen_cert_client_crt_vrfy, /* gen client cert vrfy */
54 _gnutls_gen_cert_server_cert_req, /* server cert request */
56 _gnutls_proc_crt,
57 _gnutls_proc_crt,
58 NULL, /* proc server kx */
59 proc_rsa_client_kx, /* proc client kx */
60 _gnutls_proc_cert_client_crt_vrfy, /* proc client cert vrfy */
61 _gnutls_proc_cert_cert_req /* proc server cert request */
64 /* This function reads the RSA parameters from peer's certificate;
66 static int
67 _gnutls_get_public_rsa_params (gnutls_session_t session,
68 gnutls_pk_params_st * params)
70 int ret;
71 cert_auth_info_t info;
72 gnutls_pcert_st peer_cert;
73 unsigned int i;
75 /* normal non export case */
77 info = _gnutls_get_auth_info (session);
79 if (info == NULL || info->ncerts == 0)
81 gnutls_assert ();
82 return GNUTLS_E_INTERNAL_ERROR;
85 ret =
86 _gnutls_get_auth_info_pcert (&peer_cert,
87 session->security_parameters.cert_type,
88 info);
90 if (ret < 0)
92 gnutls_assert ();
93 return ret;
96 gnutls_pk_params_init(params);
97 params->params_nr = RSA_PUBLIC_PARAMS;
99 /* EXPORT case: */
100 if (_gnutls_cipher_suite_get_kx_algo
101 (session->security_parameters.cipher_suite) ==
102 GNUTLS_KX_RSA_EXPORT &&
103 _gnutls_pubkey_is_over_rsa_512(peer_cert.pubkey) == 0)
105 if (session->key->rsa[0] == NULL || session->key->rsa[1] == NULL)
107 gnutls_assert ();
108 ret = GNUTLS_E_INTERNAL_ERROR;
109 goto cleanup;
112 for (i = 0; i < params->params_nr; i++)
114 params->params[i] = _gnutls_mpi_copy (session->key->rsa[i]);
117 ret = 0;
118 goto cleanup;
121 ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, params);
122 if (ret < 0)
124 ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
125 goto cleanup;
128 ret = 0;
130 cleanup:
131 gnutls_pcert_deinit (&peer_cert);
133 return 0;
136 static int
137 proc_rsa_client_kx (gnutls_session_t session, uint8_t * data,
138 size_t _data_size)
140 gnutls_datum_t plaintext;
141 gnutls_datum_t ciphertext;
142 int ret, dsize;
143 int randomize_key = 0;
144 ssize_t data_size = _data_size;
146 if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
148 /* SSL 3.0
150 ciphertext.data = data;
151 ciphertext.size = data_size;
153 else
155 /* TLS 1.0
157 DECR_LEN (data_size, 2);
158 ciphertext.data = &data[2];
159 dsize = _gnutls_read_uint16 (data);
161 if (dsize != data_size)
163 gnutls_assert ();
164 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
166 ciphertext.size = dsize;
169 ret =
170 gnutls_privkey_decrypt_data (session->internals.selected_key, 0,
171 &ciphertext, &plaintext);
173 if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE)
175 /* In case decryption fails then don't inform
176 * the peer. Just use a random key. (in order to avoid
177 * attack against pkcs-1 formating).
179 gnutls_assert ();
180 _gnutls_audit_log (session, "auth_rsa: Possible PKCS #1 format attack\n");
181 randomize_key = 1;
183 else
185 /* If the secret was properly formatted, then
186 * check the version number.
188 if (_gnutls_get_adv_version_major (session) != plaintext.data[0]
189 || _gnutls_get_adv_version_minor (session) != plaintext.data[1])
191 /* No error is returned here, if the version number check
192 * fails. We proceed normally.
193 * That is to defend against the attack described in the paper
194 * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
195 * Ondej Pokorny and Tomas Rosa.
197 gnutls_assert ();
198 _gnutls_audit_log
199 (session, "auth_rsa: Possible PKCS #1 version check format attack\n");
203 if (randomize_key != 0)
205 session->key->key.size = GNUTLS_MASTER_SIZE;
206 session->key->key.data = gnutls_malloc (session->key->key.size);
207 if (session->key->key.data == NULL)
209 gnutls_assert ();
210 return GNUTLS_E_MEMORY_ERROR;
213 /* we do not need strong random numbers here.
215 ret = _gnutls_rnd (GNUTLS_RND_NONCE, session->key->key.data,
216 session->key->key.size);
217 if (ret < 0)
219 gnutls_assert ();
220 return ret;
224 else
226 session->key->key.data = plaintext.data;
227 session->key->key.size = plaintext.size;
230 /* This is here to avoid the version check attack
231 * discussed above.
233 session->key->key.data[0] = _gnutls_get_adv_version_major (session);
234 session->key->key.data[1] = _gnutls_get_adv_version_minor (session);
236 return 0;
241 /* return RSA(random) using the peers public key
244 _gnutls_gen_rsa_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
246 cert_auth_info_t auth = session->key->auth_info;
247 gnutls_datum_t sdata; /* data to send */
248 gnutls_pk_params_st params;
249 int ret;
250 gnutls_protocol_t ver;
252 if (auth == NULL)
254 /* this shouldn't have happened. The proc_certificate
255 * function should have detected that.
257 gnutls_assert ();
258 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
261 session->key->key.size = GNUTLS_MASTER_SIZE;
262 session->key->key.data = gnutls_malloc (session->key->key.size);
264 if (session->key->key.data == NULL)
266 gnutls_assert ();
267 return GNUTLS_E_MEMORY_ERROR;
270 ret = _gnutls_rnd (GNUTLS_RND_RANDOM, session->key->key.data,
271 session->key->key.size);
272 if (ret < 0)
274 gnutls_assert ();
275 return ret;
278 ver = _gnutls_get_adv_version (session);
280 if (session->internals.rsa_pms_version[0] == 0)
282 session->key->key.data[0] = _gnutls_version_get_major (ver);
283 session->key->key.data[1] = _gnutls_version_get_minor (ver);
285 else
286 { /* use the version provided */
287 session->key->key.data[0] = session->internals.rsa_pms_version[0];
288 session->key->key.data[1] = session->internals.rsa_pms_version[1];
291 /* move RSA parameters to key (session).
293 if ((ret =
294 _gnutls_get_public_rsa_params (session, &params)) < 0)
296 gnutls_assert ();
297 return ret;
300 ret =
301 _gnutls_pk_encrypt (GNUTLS_PK_RSA, &sdata, &session->key->key,
302 &params);
304 gnutls_pk_params_release(&params);
306 if (ret < 0)
307 return gnutls_assert_val(ret);
310 if (gnutls_protocol_get_version (session) == GNUTLS_SSL3)
312 /* SSL 3.0 */
313 _gnutls_buffer_replace_data( data, &sdata);
315 return data->length;
317 else
318 { /* TLS 1 */
319 ret = _gnutls_buffer_append_data_prefix( data, 16, sdata.data, sdata.size);
321 _gnutls_free_datum (&sdata);
322 return ret;