2 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2009 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 everything for the Ephemeral Diffie-Hellman
26 * (DHE) key exchange. This is used in the handshake procedure of the
27 * certificate authentication.
30 #include "gnutls_int.h"
31 #include "gnutls_auth.h"
32 #include "gnutls_errors.h"
33 #include "gnutls_dh.h"
34 #include "gnutls_num.h"
35 #include "gnutls_sig.h"
36 #include <gnutls_datum.h>
37 #include <gnutls_algorithms.h>
38 #include <auth_cert.h>
39 #include <gnutls_x509.h>
40 #include <gnutls_state.h>
41 #include <auth_dh_common.h>
43 static int gen_dhe_server_kx (gnutls_session_t
, opaque
**);
44 static int proc_dhe_server_kx (gnutls_session_t
, opaque
*, size_t);
45 static int proc_dhe_client_kx (gnutls_session_t
, opaque
*, size_t);
47 const mod_auth_st dhe_rsa_auth_struct
= {
49 _gnutls_gen_cert_server_certificate
,
50 _gnutls_gen_cert_client_certificate
,
52 _gnutls_gen_dh_common_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_cert_server_certificate
,
57 _gnutls_proc_cert_client_certificate
,
60 _gnutls_proc_cert_client_cert_vrfy
, /* proc client cert vrfy */
61 _gnutls_proc_cert_cert_req
/* proc server cert request */
64 const mod_auth_st dhe_dss_auth_struct
= {
66 _gnutls_gen_cert_server_certificate
,
67 _gnutls_gen_cert_client_certificate
,
69 _gnutls_gen_dh_common_client_kx
,
70 _gnutls_gen_cert_client_cert_vrfy
, /* gen client cert vrfy */
71 _gnutls_gen_cert_server_cert_req
, /* server cert request */
73 _gnutls_proc_cert_server_certificate
,
74 _gnutls_proc_cert_client_certificate
,
77 _gnutls_proc_cert_client_cert_vrfy
, /* proc client cert vrfy */
78 _gnutls_proc_cert_cert_req
/* proc server cert request */
83 gen_dhe_server_kx (gnutls_session_t session
, opaque
** data
)
87 int ret
= 0, data_size
;
88 gnutls_cert
*apr_cert_list
;
89 gnutls_privkey
*apr_pkey
;
90 int apr_cert_list_length
;
91 gnutls_datum_t signature
, ddata
;
92 gnutls_certificate_credentials_t cred
;
93 gnutls_dh_params_t dh_params
;
94 gnutls_sign_algorithm_t sign_algo
;
95 gnutls_protocol_t ver
= gnutls_protocol_get_version (session
);
97 cred
= (gnutls_certificate_credentials_t
)
98 _gnutls_get_cred (session
->key
, GNUTLS_CRD_CERTIFICATE
, NULL
);
102 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
105 /* find the appropriate certificate */
107 _gnutls_get_selected_cert (session
, &apr_cert_list
,
108 &apr_cert_list_length
, &apr_pkey
)) < 0)
115 _gnutls_get_dh_params (cred
->dh_params
, cred
->params_func
, session
);
116 mpis
= _gnutls_dh_params_to_mpi (dh_params
);
120 return GNUTLS_E_NO_TEMPORARY_DH_PARAMS
;
126 if ((ret
= _gnutls_auth_info_set (session
, GNUTLS_CRD_CERTIFICATE
,
127 sizeof (cert_auth_info_st
), 0)) < 0)
133 _gnutls_dh_set_group (session
, g
, p
);
135 ret
= _gnutls_dh_common_print_server_kx (session
, g
, p
, data
, 0);
143 /* Generate the signature. */
146 ddata
.size
= data_size
;
148 if (apr_cert_list_length
> 0)
151 _gnutls_handshake_sign_data (session
, &apr_cert_list
[0],
152 apr_pkey
, &ddata
, &signature
,
163 return data_size
; /* do not put a signature - ILLEGAL! */
166 *data
= gnutls_realloc_fast (*data
, data_size
+ signature
.size
+ 4);
169 _gnutls_free_datum (&signature
);
171 return GNUTLS_E_MEMORY_ERROR
;
174 if (_gnutls_version_has_selectable_sighash (ver
))
176 sign_algorithm_st aid
;
178 if (sign_algo
== GNUTLS_SIGN_UNKNOWN
)
180 _gnutls_free_datum (&signature
);
182 return GNUTLS_E_UNKNOWN_PK_ALGORITHM
;
185 aid
= _gnutls_sign_to_tls_aid (sign_algo
);
186 (*data
)[data_size
++] = aid
.hash_algorithm
;
187 (*data
)[data_size
++] = aid
.sign_algorithm
;
190 _gnutls_write_datum16 (&(*data
)[data_size
], signature
);
191 data_size
+= signature
.size
+ 2;
193 _gnutls_free_datum (&signature
);
199 proc_dhe_server_kx (gnutls_session_t session
, opaque
* data
,
204 gnutls_datum_t vparams
, signature
;
206 cert_auth_info_t info
= _gnutls_get_auth_info (session
);
207 ssize_t data_size
= _data_size
;
208 gnutls_cert peer_cert
;
209 gnutls_sign_algorithm_t sign_algo
= GNUTLS_SIGN_UNKNOWN
;
210 gnutls_protocol_t ver
= gnutls_protocol_get_version (session
);
212 if (info
== NULL
|| info
->ncerts
== 0)
215 /* we need this in order to get peer's certificate */
216 return GNUTLS_E_INTERNAL_ERROR
;
219 ret
= _gnutls_proc_dh_common_server_kx (session
, data
, _data_size
, 0);
226 /* VERIFY SIGNATURE */
231 sigdata
= &data
[vparams
.size
];
232 if (_gnutls_version_has_selectable_sighash (ver
))
234 sign_algorithm_st aid
;
236 DECR_LEN (data_size
, 1);
237 aid
.hash_algorithm
= *sigdata
++;
238 DECR_LEN (data_size
, 1);
239 aid
.sign_algorithm
= *sigdata
++;
240 sign_algo
= _gnutls_tls_aid_to_sign (&aid
);
241 if (sign_algo
== GNUTLS_SIGN_UNKNOWN
)
244 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM
;
247 DECR_LEN (data_size
, 2);
248 sigsize
= _gnutls_read_uint16 (sigdata
);
251 DECR_LEN (data_size
, sigsize
);
252 signature
.data
= sigdata
;
253 signature
.size
= sigsize
;
256 _gnutls_get_auth_info_gcert (&peer_cert
,
257 session
->security_parameters
.cert_type
,
258 info
, CERT_NO_COPY
)) < 0)
265 _gnutls_handshake_verify_data (session
, &peer_cert
, &vparams
, &signature
,
268 _gnutls_gcert_deinit (&peer_cert
);
281 proc_dhe_client_kx (gnutls_session_t session
, opaque
* data
,
284 gnutls_certificate_credentials_t cred
;
287 const bigint_t
*mpis
;
288 gnutls_dh_params_t dh_params
;
290 cred
= (gnutls_certificate_credentials_t
)
291 _gnutls_get_cred (session
->key
, GNUTLS_CRD_CERTIFICATE
, NULL
);
295 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
299 _gnutls_get_dh_params (cred
->dh_params
, cred
->params_func
, session
);
300 mpis
= _gnutls_dh_params_to_mpi (dh_params
);
304 return GNUTLS_E_NO_TEMPORARY_DH_PARAMS
;
310 ret
= _gnutls_proc_dh_common_client_kx (session
, data
, _data_size
, g
, p
);