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,
25 /* This file contains the RSA key exchange part of the certificate
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"
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>
41 #include <gnutls_sig.h>
42 #include <gnutls_x509.h>
45 int _gnutls_gen_rsa_client_kx (gnutls_session_t
, opaque
**);
46 int _gnutls_proc_rsa_client_kx (gnutls_session_t
, opaque
*, size_t);
48 const mod_auth_st rsa_auth_struct
= {
50 _gnutls_gen_cert_server_certificate
,
51 _gnutls_gen_cert_client_certificate
,
52 NULL
, /* gen server kx */
53 _gnutls_gen_rsa_client_kx
,
54 _gnutls_gen_cert_client_cert_vrfy
, /* gen client cert vrfy */
55 _gnutls_gen_cert_server_cert_req
, /* server cert request */
57 _gnutls_proc_cert_server_certificate
,
58 _gnutls_proc_cert_client_certificate
,
59 NULL
, /* proc server kx */
60 _gnutls_proc_rsa_client_kx
, /* proc client kx */
61 _gnutls_proc_cert_client_cert_vrfy
, /* proc client cert vrfy */
62 _gnutls_proc_cert_cert_req
/* proc server cert request */
65 /* This function reads the RSA parameters from peer's certificate;
68 _gnutls_get_public_rsa_params (gnutls_session_t session
,
69 mpi_t params
[MAX_PUBLIC_PARAMS_SIZE
],
73 cert_auth_info_t info
;
74 gnutls_cert peer_cert
;
77 /* normal non export case */
79 info
= _gnutls_get_auth_info (session
);
81 if (info
== NULL
|| info
->ncerts
== 0)
84 return GNUTLS_E_INTERNAL_ERROR
;
88 _gnutls_raw_cert_to_gcert (&peer_cert
,
89 session
->security_parameters
.cert_type
,
90 &info
->raw_certificate_list
[0],
91 CERT_ONLY_PUBKEY
| CERT_NO_COPY
);
101 if (_gnutls_cipher_suite_get_kx_algo
102 (&session
->security_parameters
.current_cipher_suite
)
103 == GNUTLS_KX_RSA_EXPORT
104 && _gnutls_mpi_get_nbits (peer_cert
.params
[0]) > 512)
107 _gnutls_gcert_deinit (&peer_cert
);
109 if (session
->key
->rsa
[0] == NULL
|| session
->key
->rsa
[1] == NULL
)
112 return GNUTLS_E_INTERNAL_ERROR
;
118 return GNUTLS_E_INTERNAL_ERROR
;
121 for (i
= 0; i
< *params_len
; i
++)
123 params
[i
] = _gnutls_mpi_copy (session
->key
->rsa
[i
]);
129 /* end of export case */
131 if (*params_len
< peer_cert
.params_size
)
134 return GNUTLS_E_INTERNAL_ERROR
;
136 *params_len
= peer_cert
.params_size
;
138 for (i
= 0; i
< *params_len
; i
++)
140 params
[i
] = _gnutls_mpi_copy (peer_cert
.params
[i
]);
142 _gnutls_gcert_deinit (&peer_cert
);
147 /* This function reads the RSA parameters from the private key
150 _gnutls_get_private_rsa_params (gnutls_session_t session
,
151 mpi_t
** params
, int *params_size
)
154 gnutls_certificate_credentials_t cred
;
155 gnutls_rsa_params_t rsa_params
;
157 cred
= (gnutls_certificate_credentials_t
)
158 _gnutls_get_cred (session
->key
, GNUTLS_CRD_CERTIFICATE
, NULL
);
162 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
165 if (session
->internals
.selected_cert_list
== NULL
)
168 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
172 _gnutls_mpi_get_nbits (session
->internals
.selected_cert_list
[0].
175 if (_gnutls_cipher_suite_get_kx_algo
176 (&session
->security_parameters
.current_cipher_suite
)
177 == GNUTLS_KX_RSA_EXPORT
&& bits
> 512)
181 _gnutls_certificate_get_rsa_params (cred
->rsa_params
,
182 cred
->params_func
, session
);
184 if (rsa_params
== NULL
)
187 return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS
;
190 /* In the export case, we do use temporary RSA params
191 * of 512 bits size. The params in the certificate are
192 * used to sign this temporary stuff.
194 *params_size
= RSA_PRIVATE_PARAMS
;
195 *params
= rsa_params
->params
;
200 /* non export cipher suites. */
202 *params_size
= session
->internals
.selected_key
->params_size
;
203 *params
= session
->internals
.selected_key
->params
;
209 _gnutls_proc_rsa_client_kx (gnutls_session_t session
, opaque
* data
,
212 gnutls_datum_t plaintext
;
213 gnutls_datum_t ciphertext
;
217 int randomize_key
= 0;
218 ssize_t data_size
= _data_size
;
220 if (gnutls_protocol_get_version (session
) == GNUTLS_SSL3
)
224 ciphertext
.data
= data
;
225 ciphertext
.size
= data_size
;
231 DECR_LEN (data_size
, 2);
232 ciphertext
.data
= &data
[2];
233 dsize
= _gnutls_read_uint16 (data
);
235 if (dsize
!= data_size
)
238 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
240 ciphertext
.size
= dsize
;
243 ret
= _gnutls_get_private_rsa_params (session
, ¶ms
, ¶ms_len
);
250 ret
= _gnutls_pkcs1_rsa_decrypt (&plaintext
, &ciphertext
, params
, params_len
, 2); /* btype==2 */
252 if (ret
< 0 || plaintext
.size
!= TLS_MASTER_SIZE
)
254 /* In case decryption fails then don't inform
255 * the peer. Just use a random key. (in order to avoid
256 * attack against pkcs-1 formating).
259 _gnutls_x509_log ("auth_rsa: Possible PKCS #1 format attack\n");
264 /* If the secret was properly formatted, then
265 * check the version number.
267 if (_gnutls_get_adv_version_major (session
) != plaintext
.data
[0]
268 || _gnutls_get_adv_version_minor (session
) != plaintext
.data
[1])
270 /* No error is returned here, if the version number check
271 * fails. We proceed normally.
272 * That is to defend against the attack described in the paper
273 * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
274 * Ondej Pokorny and Tomas Rosa.
278 ("auth_rsa: Possible PKCS #1 version check format attack\n");
282 if (randomize_key
!= 0)
284 session
->key
->key
.size
= TLS_MASTER_SIZE
;
285 session
->key
->key
.data
= gnutls_malloc (session
->key
->key
.size
);
286 if (session
->key
->key
.data
== NULL
)
289 return GNUTLS_E_MEMORY_ERROR
;
292 /* we do not need strong random numbers here.
294 if (gc_nonce (session
->key
->key
.data
, session
->key
->key
.size
) != GC_OK
)
297 return GNUTLS_E_RANDOM_FAILED
;
303 session
->key
->key
.data
= plaintext
.data
;
304 session
->key
->key
.size
= plaintext
.size
;
307 /* This is here to avoid the version check attack
310 session
->key
->key
.data
[0] = _gnutls_get_adv_version_major (session
);
311 session
->key
->key
.data
[1] = _gnutls_get_adv_version_minor (session
);
318 /* return RSA(random) using the peers public key
321 _gnutls_gen_rsa_client_kx (gnutls_session_t session
, opaque
** data
)
323 cert_auth_info_t auth
= session
->key
->auth_info
;
324 gnutls_datum_t sdata
; /* data to send */
325 mpi_t params
[MAX_PUBLIC_PARAMS_SIZE
];
326 int params_len
= MAX_PUBLIC_PARAMS_SIZE
;
328 gnutls_protocol_t ver
;
332 /* this shouldn't have happened. The proc_certificate
333 * function should have detected that.
336 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
339 session
->key
->key
.size
= TLS_MASTER_SIZE
;
340 session
->key
->key
.data
= gnutls_secure_malloc (session
->key
->key
.size
);
342 if (session
->key
->key
.data
== NULL
)
345 return GNUTLS_E_MEMORY_ERROR
;
348 if (gc_pseudo_random (session
->key
->key
.data
,
349 session
->key
->key
.size
) != GC_OK
)
352 return GNUTLS_E_RANDOM_FAILED
;
355 ver
= _gnutls_get_adv_version (session
);
357 if (session
->internals
.rsa_pms_version
[0] == 0)
359 session
->key
->key
.data
[0] = _gnutls_version_get_major (ver
);
360 session
->key
->key
.data
[1] = _gnutls_version_get_minor (ver
);
363 { /* use the version provided */
364 session
->key
->key
.data
[0] = session
->internals
.rsa_pms_version
[0];
365 session
->key
->key
.data
[1] = session
->internals
.rsa_pms_version
[1];
368 /* move RSA parameters to key (session).
371 _gnutls_get_public_rsa_params (session
, params
, ¶ms_len
)) < 0)
378 _gnutls_pkcs1_rsa_encrypt (&sdata
, &session
->key
->key
,
379 params
, params_len
, 2)) < 0)
385 for (i
= 0; i
< params_len
; i
++)
386 _gnutls_mpi_release (¶ms
[i
]);
388 if (gnutls_protocol_get_version (session
) == GNUTLS_SSL3
)
396 *data
= gnutls_malloc (sdata
.size
+ 2);
399 _gnutls_free_datum (&sdata
);
400 return GNUTLS_E_MEMORY_ERROR
;
402 _gnutls_write_datum16 (*data
, sdata
);
403 ret
= sdata
.size
+ 2;
404 _gnutls_free_datum (&sdata
);