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>
40 #include <gnutls_rsa_export.h>
41 #include <gnutls_state.h>
43 #include <abstract_int.h>
45 int _gnutls_gen_rsa_client_kx (gnutls_session_t
, gnutls_buffer_st
*);
46 static int gen_rsa_export_server_kx (gnutls_session_t
, gnutls_buffer_st
*);
47 static int proc_rsa_export_server_kx (gnutls_session_t
, uint8_t *, size_t);
48 static int proc_rsa_export_client_kx (gnutls_session_t session
, uint8_t * data
,
51 const mod_auth_st rsa_export_auth_struct
= {
53 _gnutls_gen_cert_server_crt
,
54 _gnutls_gen_cert_client_crt
,
55 gen_rsa_export_server_kx
,
56 _gnutls_gen_rsa_client_kx
,
57 _gnutls_gen_cert_client_crt_vrfy
, /* gen client cert vrfy */
58 _gnutls_gen_cert_server_cert_req
, /* server cert request */
62 proc_rsa_export_server_kx
,
63 proc_rsa_export_client_kx
, /* proc client kx */
64 _gnutls_proc_cert_client_crt_vrfy
, /* proc client cert vrfy */
65 _gnutls_proc_cert_cert_req
/* proc server cert request */
68 /* This function reads the RSA parameters from the private key
71 _gnutls_get_private_rsa_params (gnutls_session_t session
,
72 gnutls_pk_params_st
** params
)
75 gnutls_certificate_credentials_t cred
;
76 gnutls_rsa_params_t rsa_params
;
78 cred
= (gnutls_certificate_credentials_t
)
79 _gnutls_get_cred (session
->key
, GNUTLS_CRD_CERTIFICATE
, NULL
);
83 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
86 if (session
->internals
.selected_cert_list
== NULL
)
89 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
92 ret
= _gnutls_pubkey_is_over_rsa_512(session
->internals
.selected_cert_list
[0].pubkey
);
94 if (_gnutls_cipher_suite_get_kx_algo
95 (session
->security_parameters
.cipher_suite
)
96 != GNUTLS_KX_RSA_EXPORT
|| ret
< 0)
99 return GNUTLS_E_INVALID_REQUEST
;
103 _gnutls_certificate_get_rsa_params (cred
->rsa_params
,
104 cred
->params_func
, session
);
106 if (rsa_params
== NULL
)
109 return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS
;
112 /* In the export case, we do use temporary RSA params
113 * of 512 bits size. The params in the certificate are
114 * used to sign this temporary stuff.
116 *params
= &rsa_params
->params
;
122 proc_rsa_export_client_kx (gnutls_session_t session
, uint8_t * data
,
125 gnutls_datum_t plaintext
;
126 gnutls_datum_t ciphertext
;
128 gnutls_pk_params_st
*params
;
129 int randomize_key
= 0;
130 ssize_t data_size
= _data_size
;
132 if (gnutls_protocol_get_version (session
) == GNUTLS_SSL3
)
136 ciphertext
.data
= data
;
137 ciphertext
.size
= data_size
;
143 DECR_LEN (data_size
, 2);
144 ciphertext
.data
= &data
[2];
145 dsize
= _gnutls_read_uint16 (data
);
147 if (dsize
!= data_size
)
150 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
152 ciphertext
.size
= dsize
;
155 ret
= _gnutls_get_private_rsa_params (session
, ¶ms
);
162 ret
= _gnutls_pk_decrypt (GNUTLS_PK_RSA
, &plaintext
, &ciphertext
, params
);
164 if (ret
< 0 || plaintext
.size
!= GNUTLS_MASTER_SIZE
)
166 /* In case decryption fails then don't inform
167 * the peer. Just use a random key. (in order to avoid
168 * attack against pkcs-1 formating).
171 _gnutls_audit_log (session
, "auth_rsa: Possible PKCS #1 format attack\n");
176 /* If the secret was properly formatted, then
177 * check the version number.
179 if (_gnutls_get_adv_version_major (session
) != plaintext
.data
[0]
180 || _gnutls_get_adv_version_minor (session
) != plaintext
.data
[1])
182 /* No error is returned here, if the version number check
183 * fails. We proceed normally.
184 * That is to defend against the attack described in the paper
185 * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
186 * Ondej Pokorny and Tomas Rosa.
190 (session
, "auth_rsa: Possible PKCS #1 version check format attack\n");
194 if (randomize_key
!= 0)
196 session
->key
->key
.size
= GNUTLS_MASTER_SIZE
;
197 session
->key
->key
.data
= gnutls_malloc (session
->key
->key
.size
);
198 if (session
->key
->key
.data
== NULL
)
201 return GNUTLS_E_MEMORY_ERROR
;
204 /* we do not need strong random numbers here.
206 ret
= _gnutls_rnd (GNUTLS_RND_NONCE
, session
->key
->key
.data
,
207 session
->key
->key
.size
);
217 session
->key
->key
.data
= plaintext
.data
;
218 session
->key
->key
.size
= plaintext
.size
;
221 /* This is here to avoid the version check attack
224 session
->key
->key
.data
[0] = _gnutls_get_adv_version_major (session
);
225 session
->key
->key
.data
[1] = _gnutls_get_adv_version_minor (session
);
231 gen_rsa_export_server_kx (gnutls_session_t session
, gnutls_buffer_st
* data
)
233 gnutls_rsa_params_t rsa_params
;
234 const gnutls_pk_params_st
*rsa_mpis
;
236 gnutls_pcert_st
*apr_cert_list
;
237 gnutls_privkey_t apr_pkey
;
238 int apr_cert_list_length
;
239 gnutls_datum_t signature
, ddata
;
240 gnutls_certificate_credentials_t cred
;
241 gnutls_sign_algorithm_t sign_algo
;
242 unsigned int bits
= 0;
244 cred
= (gnutls_certificate_credentials_t
)
245 _gnutls_get_cred (session
->key
, GNUTLS_CRD_CERTIFICATE
, NULL
);
249 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
252 /* find the appropriate certificate */
254 _gnutls_get_selected_cert (session
, &apr_cert_list
,
255 &apr_cert_list_length
, &apr_pkey
)) < 0)
261 /* abort sending this message if we have a certificate
262 * of 512 bits or less.
264 gnutls_privkey_get_pk_algorithm (apr_pkey
, &bits
);
265 if (apr_pkey
&& bits
<= 512)
268 return GNUTLS_E_INT_RET_0
;
272 _gnutls_certificate_get_rsa_params (cred
->rsa_params
, cred
->params_func
,
274 rsa_mpis
= _gnutls_rsa_params_to_mpi (rsa_params
);
275 if (rsa_mpis
== NULL
)
278 return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS
;
281 if ((ret
= _gnutls_auth_info_set (session
, GNUTLS_CRD_CERTIFICATE
,
282 sizeof (cert_auth_info_st
), 0)) < 0)
288 _gnutls_rsa_export_set_pubkey (session
, rsa_mpis
->params
[1], rsa_mpis
->params
[0]);
290 ret
= _gnutls_buffer_append_mpi( data
, 16, rsa_mpis
->params
[0], 0);
292 return gnutls_assert_val(ret
);
294 ret
= _gnutls_buffer_append_mpi( data
, 16, rsa_mpis
->params
[1], 0);
296 return gnutls_assert_val(ret
);
298 /* Generate the signature. */
300 ddata
.data
= data
->data
;
301 ddata
.size
= data
->length
;
303 if (apr_cert_list_length
> 0)
306 _gnutls_handshake_sign_data (session
, &apr_cert_list
[0],
307 apr_pkey
, &ddata
, &signature
,
317 return data
->length
; /* do not put a signature - ILLEGAL! */
320 ret
= _gnutls_buffer_append_data_prefix( data
, 16, signature
.data
, signature
.size
);
321 _gnutls_free_datum (&signature
);
324 return gnutls_assert_val(ret
);
329 /* if the peer's certificate is of 512 bits or less, returns non (0).
332 _gnutls_peers_cert_less_512 (gnutls_session_t session
)
334 gnutls_pcert_st peer_cert
;
336 cert_auth_info_t info
= _gnutls_get_auth_info (session
);
338 if (info
== NULL
|| info
->ncerts
== 0)
341 /* we need this in order to get peer's certificate */
346 _gnutls_get_auth_info_pcert (&peer_cert
,
347 session
->security_parameters
.cert_type
,
354 if (gnutls_pubkey_get_pk_algorithm(peer_cert
.pubkey
, NULL
) != GNUTLS_PK_RSA
)
357 gnutls_pcert_deinit (&peer_cert
);
361 if (_gnutls_pubkey_is_over_rsa_512(peer_cert
.pubkey
) < 0)
363 gnutls_pcert_deinit (&peer_cert
);
367 gnutls_pcert_deinit (&peer_cert
);
373 proc_rsa_export_server_kx (gnutls_session_t session
,
374 uint8_t * data
, size_t _data_size
)
381 gnutls_datum_t vparams
, signature
;
383 ssize_t data_size
= _data_size
;
384 cert_auth_info_t info
;
385 gnutls_pcert_st peer_cert
;
387 info
= _gnutls_get_auth_info (session
);
388 if (info
== NULL
|| info
->ncerts
== 0)
391 /* we need this in order to get peer's certificate */
392 return GNUTLS_E_INTERNAL_ERROR
;
398 DECR_LEN (data_size
, 2);
399 n_m
= _gnutls_read_uint16 (&data
[i
]);
402 DECR_LEN (data_size
, n_m
);
406 DECR_LEN (data_size
, 2);
407 n_e
= _gnutls_read_uint16 (&data
[i
]);
410 DECR_LEN (data_size
, n_e
);
416 if (_gnutls_mpi_scan_nz (&session
->key
->rsa
[0], data_m
, _n_m
) != 0)
419 return GNUTLS_E_MPI_SCAN_FAILED
;
422 if (_gnutls_mpi_scan_nz (&session
->key
->rsa
[1], data_e
, _n_e
) != 0)
425 return GNUTLS_E_MPI_SCAN_FAILED
;
428 _gnutls_rsa_export_set_pubkey (session
, session
->key
->rsa
[1],
429 session
->key
->rsa
[0]);
431 /* VERIFY SIGNATURE */
433 vparams
.size
= n_m
+ n_e
+ 4;
436 DECR_LEN (data_size
, 2);
437 sigsize
= _gnutls_read_uint16 (&data
[vparams
.size
]);
439 DECR_LEN (data_size
, sigsize
);
440 signature
.data
= &data
[vparams
.size
+ 2];
441 signature
.size
= sigsize
;
444 _gnutls_get_auth_info_pcert (&peer_cert
,
445 session
->security_parameters
.cert_type
,
453 _gnutls_handshake_verify_data (session
, &peer_cert
, &vparams
, &signature
,
454 GNUTLS_SIGN_UNKNOWN
);
456 gnutls_pcert_deinit (&peer_cert
);