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.h"
31 #include "gnutls_errors.h"
32 #include "gnutls_dh.h"
33 #include "gnutls_num.h"
34 #include "gnutls_datum.h"
35 #include "auth_cert.h"
36 #include <gnutls_pk.h>
37 #include <gnutls_algorithms.h>
38 #include <gnutls_global.h>
40 #include <gnutls_sig.h>
41 #include <gnutls_x509.h>
42 #include <gnutls_rsa_export.h>
43 #include <gnutls_state.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);
47 static int gen_rsa_export_server_kx (gnutls_session_t
, opaque
**);
48 static int proc_rsa_export_server_kx (gnutls_session_t
, opaque
*, size_t);
50 const mod_auth_st rsa_export_auth_struct
= {
52 _gnutls_gen_cert_server_certificate
,
53 _gnutls_gen_cert_client_certificate
,
54 gen_rsa_export_server_kx
,
55 _gnutls_gen_rsa_client_kx
,
56 _gnutls_gen_cert_client_cert_vrfy
, /* gen client cert vrfy */
57 _gnutls_gen_cert_server_cert_req
, /* server cert request */
59 _gnutls_proc_cert_server_certificate
,
60 _gnutls_proc_cert_client_certificate
,
61 proc_rsa_export_server_kx
,
62 _gnutls_proc_rsa_client_kx
, /* proc client kx */
63 _gnutls_proc_cert_client_cert_vrfy
, /* proc client cert vrfy */
64 _gnutls_proc_cert_cert_req
/* proc server cert request */
68 gen_rsa_export_server_kx (gnutls_session_t session
, opaque
** data
)
70 gnutls_rsa_params_t rsa_params
;
71 const bigint_t
*rsa_mpis
;
73 uint8_t *data_e
, *data_m
;
74 int ret
= 0, data_size
;
75 gnutls_cert
*apr_cert_list
;
76 gnutls_privkey
*apr_pkey
;
77 int apr_cert_list_length
;
78 gnutls_datum_t signature
, ddata
;
79 cert_auth_info_t info
;
80 gnutls_certificate_credentials_t cred
;
82 cred
= (gnutls_certificate_credentials_t
)
83 _gnutls_get_cred (session
->key
, GNUTLS_CRD_CERTIFICATE
, NULL
);
87 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
90 /* find the appropriate certificate */
92 _gnutls_get_selected_cert (session
, &apr_cert_list
,
93 &apr_cert_list_length
, &apr_pkey
)) < 0)
99 /* abort sending this message if we have a certificate
100 * of 512 bits or less.
102 if (apr_pkey
&& _gnutls_mpi_get_nbits (apr_pkey
->params
[0]) <= 512)
105 return GNUTLS_E_INT_RET_0
;
109 _gnutls_certificate_get_rsa_params (cred
->rsa_params
, cred
->params_func
,
111 rsa_mpis
= _gnutls_rsa_params_to_mpi (rsa_params
);
112 if (rsa_mpis
== NULL
)
115 return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS
;
118 if ((ret
= _gnutls_auth_info_set (session
, GNUTLS_CRD_CERTIFICATE
,
119 sizeof (cert_auth_info_st
), 0)) < 0)
125 info
= _gnutls_get_auth_info (session
);
126 _gnutls_rsa_export_set_pubkey (session
, rsa_mpis
[1], rsa_mpis
[0]);
128 _gnutls_mpi_print (rsa_mpis
[0], NULL
, &n_m
);
129 _gnutls_mpi_print (rsa_mpis
[1], NULL
, &n_e
);
131 (*data
) = gnutls_malloc (n_e
+ n_m
+ 4);
134 return GNUTLS_E_MEMORY_ERROR
;
137 data_m
= &(*data
)[0];
138 _gnutls_mpi_print (rsa_mpis
[0], &data_m
[2], &n_m
);
140 _gnutls_write_uint16 (n_m
, data_m
);
142 data_e
= &data_m
[2 + n_m
];
143 _gnutls_mpi_print (rsa_mpis
[1], &data_e
[2], &n_e
);
145 _gnutls_write_uint16 (n_e
, data_e
);
147 data_size
= n_m
+ n_e
+ 4;
150 /* Generate the signature. */
153 ddata
.size
= data_size
;
155 if (apr_cert_list_length
> 0)
158 _gnutls_tls_sign_params (session
, &apr_cert_list
[0],
159 apr_pkey
, &ddata
, &signature
)) < 0)
170 return data_size
; /* do not put a signature - ILLEGAL! */
173 *data
= gnutls_realloc_fast (*data
, data_size
+ signature
.size
+ 2);
176 _gnutls_free_datum (&signature
);
178 return GNUTLS_E_MEMORY_ERROR
;
181 _gnutls_write_datum16 (&((*data
)[data_size
]), signature
);
182 data_size
+= signature
.size
+ 2;
184 _gnutls_free_datum (&signature
);
189 /* if the peer's certificate is of 512 bits or less, returns non zero.
192 _gnutls_peers_cert_less_512 (gnutls_session_t session
)
194 gnutls_cert peer_cert
;
196 cert_auth_info_t info
= _gnutls_get_auth_info (session
);
198 if (info
== NULL
|| info
->ncerts
== 0)
201 /* we need this in order to get peer's certificate */
206 _gnutls_get_auth_info_gcert (&peer_cert
,
207 session
->security_parameters
.cert_type
,
208 info
, CERT_NO_COPY
)) < 0)
214 if (peer_cert
.subject_pk_algorithm
!= GNUTLS_PK_RSA
)
217 _gnutls_gcert_deinit (&peer_cert
);
221 if (_gnutls_mpi_get_nbits (peer_cert
.params
[0]) <= 512)
223 _gnutls_gcert_deinit (&peer_cert
);
227 _gnutls_gcert_deinit (&peer_cert
);
233 proc_rsa_export_server_kx (gnutls_session_t session
,
234 opaque
* data
, size_t _data_size
)
241 gnutls_datum_t vparams
, signature
;
243 ssize_t data_size
= _data_size
;
244 cert_auth_info_t info
;
245 gnutls_cert peer_cert
;
247 info
= _gnutls_get_auth_info (session
);
248 if (info
== NULL
|| info
->ncerts
== 0)
251 /* we need this in order to get peer's certificate */
252 return GNUTLS_E_INTERNAL_ERROR
;
258 DECR_LEN (data_size
, 2);
259 n_m
= _gnutls_read_uint16 (&data
[i
]);
262 DECR_LEN (data_size
, n_m
);
266 DECR_LEN (data_size
, 2);
267 n_e
= _gnutls_read_uint16 (&data
[i
]);
270 DECR_LEN (data_size
, n_e
);
277 if (_gnutls_mpi_scan_nz (&session
->key
->rsa
[0], data_m
, _n_m
) != 0)
280 return GNUTLS_E_MPI_SCAN_FAILED
;
283 if (_gnutls_mpi_scan_nz (&session
->key
->rsa
[1], data_e
, _n_e
) != 0)
286 return GNUTLS_E_MPI_SCAN_FAILED
;
289 _gnutls_rsa_export_set_pubkey (session
, session
->key
->rsa
[1],
290 session
->key
->rsa
[0]);
292 /* VERIFY SIGNATURE */
294 vparams
.size
= n_m
+ n_e
+ 4;
297 DECR_LEN (data_size
, 2);
298 sigsize
= _gnutls_read_uint16 (&data
[vparams
.size
]);
300 DECR_LEN (data_size
, sigsize
);
301 signature
.data
= &data
[vparams
.size
+ 2];
302 signature
.size
= sigsize
;
305 _gnutls_get_auth_info_gcert (&peer_cert
,
306 session
->security_parameters
.cert_type
,
307 info
, CERT_NO_COPY
)) < 0)
313 ret
= _gnutls_verify_sig_params (session
, &peer_cert
, &vparams
, &signature
);
315 _gnutls_gcert_deinit (&peer_cert
);