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
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>
38 #include <gnutls_sig.h>
39 #include <gnutls_x509.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
= {
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_cert_vrfy
, /* gen client cert vrfy */
54 _gnutls_gen_cert_server_cert_req
, /* server cert request */
56 _gnutls_proc_certificate
,
57 _gnutls_proc_certificate
,
58 NULL
, /* proc server kx */
59 proc_rsa_client_kx
, /* proc client kx */
60 _gnutls_proc_cert_client_cert_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;
67 _gnutls_get_public_rsa_params (gnutls_session_t session
,
68 gnutls_pk_params_st
* params
)
71 cert_auth_info_t info
;
72 gnutls_pcert_st peer_cert
;
75 /* normal non export case */
77 info
= _gnutls_get_auth_info (session
);
79 if (info
== NULL
|| info
->ncerts
== 0)
82 return GNUTLS_E_INTERNAL_ERROR
;
86 _gnutls_get_auth_info_pcert (&peer_cert
,
87 session
->security_parameters
.cert_type
,
96 gnutls_pk_params_init(params
);
97 params
->params_nr
= RSA_PUBLIC_PARAMS
;
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
)
108 ret
= GNUTLS_E_INTERNAL_ERROR
;
112 for (i
= 0; i
< params
->params_nr
; i
++)
114 params
->params
[i
] = _gnutls_mpi_copy (session
->key
->rsa
[i
]);
121 ret
= _gnutls_pubkey_get_mpis(peer_cert
.pubkey
, params
);
124 ret
= gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR
);
131 gnutls_pcert_deinit (&peer_cert
);
137 proc_rsa_client_kx (gnutls_session_t session
, uint8_t * data
,
140 gnutls_datum_t plaintext
;
141 gnutls_datum_t ciphertext
;
143 int randomize_key
= 0;
144 ssize_t data_size
= _data_size
;
146 if (gnutls_protocol_get_version (session
) == GNUTLS_SSL3
)
150 ciphertext
.data
= data
;
151 ciphertext
.size
= data_size
;
157 DECR_LEN (data_size
, 2);
158 ciphertext
.data
= &data
[2];
159 dsize
= _gnutls_read_uint16 (data
);
161 if (dsize
!= data_size
)
164 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
166 ciphertext
.size
= dsize
;
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).
180 _gnutls_audit_log (session
, "auth_rsa: Possible PKCS #1 format attack\n");
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.
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
)
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
);
226 session
->key
->key
.data
= plaintext
.data
;
227 session
->key
->key
.size
= plaintext
.size
;
230 /* This is here to avoid the version check attack
233 session
->key
->key
.data
[0] = _gnutls_get_adv_version_major (session
);
234 session
->key
->key
.data
[1] = _gnutls_get_adv_version_minor (session
);
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
;
250 gnutls_protocol_t ver
;
254 /* this shouldn't have happened. The proc_certificate
255 * function should have detected that.
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
)
267 return GNUTLS_E_MEMORY_ERROR
;
270 ret
= _gnutls_rnd (GNUTLS_RND_RANDOM
, session
->key
->key
.data
,
271 session
->key
->key
.size
);
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
);
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).
294 _gnutls_get_public_rsa_params (session
, ¶ms
)) < 0)
301 _gnutls_pkcs1_rsa_encrypt (&sdata
, &session
->key
->key
,
304 gnutls_pk_params_release(¶ms
);
307 return gnutls_assert_val(ret
);
310 if (gnutls_protocol_get_version (session
) == GNUTLS_SSL3
)
313 _gnutls_buffer_replace_data( data
, &sdata
);
319 ret
= _gnutls_buffer_append_data_prefix( data
, 16, sdata
.data
, sdata
.size
);
321 _gnutls_free_datum (&sdata
);