Fix memory leaks.
[gnutls.git] / lib / gnutls_sig.c
blob1c931e8a56a123b28c03f77278e86f50b3a54968
1 /*
2 * Copyright (C) 2001, 2004, 2005, 2006, 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,
21 * USA
25 #include <gnutls_int.h>
26 #include <gnutls_errors.h>
27 #include <x509_b64.h>
28 #include <auth_cert.h>
29 #include <gnutls_cert.h>
30 #include <libtasn1.h>
31 #include <gnutls_datum.h>
32 #include <gnutls_mpi.h>
33 #include <gnutls_global.h>
34 #include <gnutls_pk.h>
35 #include <debug.h>
36 #include <gnutls_buffers.h>
37 #include <gnutls_sig.h>
38 #include <gnutls_kx.h>
40 static int
41 _gnutls_tls_sign (gnutls_session_t session,
42 gnutls_cert * cert, gnutls_privkey * pkey,
43 const gnutls_datum_t * hash_concat,
44 gnutls_datum_t * signature);
47 /* Generates a signature of all the previous sent packets in the
48 * handshake procedure. (20040227: now it works for SSL 3.0 as well)
50 int
51 _gnutls_tls_sign_hdata (gnutls_session_t session,
52 gnutls_cert * cert, gnutls_privkey * pkey,
53 gnutls_datum_t * signature)
55 gnutls_datum_t dconcat;
56 int ret;
57 opaque concat[36];
58 digest_hd_st td_md5;
59 digest_hd_st td_sha;
60 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
62 ret = _gnutls_hash_copy (&td_sha, &session->internals.handshake_mac_handle_sha);
63 if (ret < 0)
65 gnutls_assert ();
66 return ret;
69 if (ver == GNUTLS_SSL3)
71 ret = _gnutls_generate_master (session, 1);
72 if (ret < 0)
74 gnutls_assert ();
75 return ret;
78 _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
79 session->security_parameters.
80 master_secret, TLS_MASTER_SIZE);
82 else
83 _gnutls_hash_deinit (&td_sha, &concat[16]);
85 switch (cert->subject_pk_algorithm)
87 case GNUTLS_PK_RSA:
88 ret = _gnutls_hash_copy (&td_md5, &session->internals.handshake_mac_handle_md5);
89 if (ret < 0)
91 gnutls_assert ();
92 return ret;
95 if (ver == GNUTLS_SSL3)
96 _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
97 session->security_parameters.
98 master_secret, TLS_MASTER_SIZE);
99 else
100 _gnutls_hash_deinit (&td_md5, concat);
102 dconcat.data = concat;
103 dconcat.size = 36;
104 break;
105 case GNUTLS_PK_DSA:
106 dconcat.data = &concat[16];
107 dconcat.size = 20;
108 break;
110 default:
111 gnutls_assert ();
112 return GNUTLS_E_INTERNAL_ERROR;
114 ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
115 if (ret < 0)
117 gnutls_assert ();
120 return ret;
124 /* Generates a signature of all the random data and the parameters.
125 * Used in DHE_* ciphersuites.
128 _gnutls_tls_sign_params (gnutls_session_t session, gnutls_cert * cert,
129 gnutls_privkey * pkey, gnutls_datum_t * params,
130 gnutls_datum_t * signature)
132 gnutls_datum_t dconcat;
133 int ret;
134 digest_hd_st td_sha;
135 opaque concat[36];
136 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
138 ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1);
139 if (ret < 0)
141 gnutls_assert ();
142 return ret;
145 _gnutls_hash (&td_sha, session->security_parameters.client_random,
146 TLS_RANDOM_SIZE);
147 _gnutls_hash (&td_sha, session->security_parameters.server_random,
148 TLS_RANDOM_SIZE);
149 _gnutls_hash (&td_sha, params->data, params->size);
151 switch (cert->subject_pk_algorithm)
153 case GNUTLS_PK_RSA:
154 if (ver < GNUTLS_TLS1_2)
156 digest_hd_st td_md5;
158 ret =_gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
159 if (ret < 0)
161 gnutls_assert ();
162 return ret;
165 _gnutls_hash (&td_md5, session->security_parameters.client_random,
166 TLS_RANDOM_SIZE);
167 _gnutls_hash (&td_md5, session->security_parameters.server_random,
168 TLS_RANDOM_SIZE);
169 _gnutls_hash (&td_md5, params->data, params->size);
171 _gnutls_hash_deinit (&td_md5, concat);
172 _gnutls_hash_deinit (&td_sha, &concat[16]);
174 dconcat.size = 36;
176 else
178 #if 1
179 /* Use NULL parameters. */
180 memcpy (concat,
181 "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
182 15);
183 _gnutls_hash_deinit (&td_sha, &concat[15]);
184 dconcat.size = 35;
185 #else
186 /* No parameters field. */
187 memcpy (concat,
188 "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14",
189 13);
190 _gnutls_hash_deinit (&td_sha, &concat[13]);
191 dconcat.size = 33;
192 #endif
194 dconcat.data = concat;
195 break;
196 case GNUTLS_PK_DSA:
197 _gnutls_hash_deinit (&td_sha, concat);
198 dconcat.data = concat;
199 dconcat.size = 20;
200 break;
202 default:
203 gnutls_assert ();
204 _gnutls_hash_deinit (&td_sha, NULL);
205 return GNUTLS_E_INTERNAL_ERROR;
207 ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
208 if (ret < 0)
210 gnutls_assert ();
213 return ret;
218 /* This will create a PKCS1 or DSA signature, using the given parameters, and the
219 * given data. The output will be allocated and be put in signature.
222 _gnutls_sign (gnutls_pk_algorithm_t algo, mpi_t * params,
223 int params_size, const gnutls_datum_t * data,
224 gnutls_datum_t * signature)
226 int ret;
228 switch (algo)
230 case GNUTLS_PK_RSA:
231 /* encrypt */
232 if ((ret = _gnutls_pkcs1_rsa_encrypt (signature, data, params,
233 params_size, 1)) < 0)
235 gnutls_assert ();
236 return ret;
239 break;
240 case GNUTLS_PK_DSA:
241 /* sign */
242 if ((ret = _gnutls_dsa_sign (signature, data, params, params_size)) < 0)
244 gnutls_assert ();
245 return ret;
247 break;
248 default:
249 gnutls_assert ();
250 return GNUTLS_E_INTERNAL_ERROR;
251 break;
254 return 0;
257 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
258 * Cert is the certificate of the corresponding private key. It is only checked if
259 * it supports signing.
261 static int
262 _gnutls_tls_sign (gnutls_session_t session,
263 gnutls_cert * cert, gnutls_privkey * pkey,
264 const gnutls_datum_t * hash_concat,
265 gnutls_datum_t * signature)
268 /* If our certificate supports signing
271 if (cert != NULL)
272 if (cert->key_usage != 0)
273 if (!(cert->key_usage & KEY_DIGITAL_SIGNATURE))
275 gnutls_assert ();
276 return GNUTLS_E_KEY_USAGE_VIOLATION;
279 /* External signing. */
280 if (!pkey || pkey->params_size == 0)
282 if (!session->internals.sign_func)
283 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
285 return (*session->internals.sign_func)
286 (session, session->internals.sign_func_userdata,
287 cert->cert_type, &cert->raw,
288 hash_concat, signature);
291 return _gnutls_sign (pkey->pk_algorithm, pkey->params,
292 pkey->params_size, hash_concat, signature);
295 static int
296 _gnutls_verify_sig (gnutls_cert * cert,
297 const gnutls_datum_t * hash_concat,
298 gnutls_datum_t * signature,
299 size_t sha1pos)
301 int ret;
302 gnutls_datum_t vdata;
304 if (cert->version == 0 || cert == NULL)
305 { /* this is the only way to check
306 * if it is initialized
308 gnutls_assert ();
309 return GNUTLS_E_CERTIFICATE_ERROR;
312 /* If the certificate supports signing continue.
314 if (cert != NULL)
315 if (cert->key_usage != 0)
316 if (!(cert->key_usage & KEY_DIGITAL_SIGNATURE))
318 gnutls_assert ();
319 return GNUTLS_E_KEY_USAGE_VIOLATION;
322 switch (cert->subject_pk_algorithm)
324 case GNUTLS_PK_RSA:
326 vdata.data = hash_concat->data;
327 vdata.size = hash_concat->size;
329 /* verify signature */
330 if ((ret = _gnutls_rsa_verify (&vdata, signature, cert->params,
331 cert->params_size, 1)) < 0)
333 gnutls_assert ();
334 return ret;
337 break;
338 case GNUTLS_PK_DSA:
340 vdata.data = &hash_concat->data[sha1pos];
341 vdata.size = 20; /* sha1 */
343 /* verify signature */
344 if ((ret = _gnutls_dsa_verify (&vdata, signature, cert->params,
345 cert->params_size)) < 0)
347 gnutls_assert ();
348 return ret;
351 break;
353 default:
354 gnutls_assert ();
355 return GNUTLS_E_INTERNAL_ERROR;
360 return 0;
364 /* Verifies a TLS signature (like the one in the client certificate
365 * verify message).
368 _gnutls_verify_sig_hdata (gnutls_session_t session, gnutls_cert * cert,
369 gnutls_datum_t * signature)
371 int ret;
372 opaque concat[36];
373 digest_hd_st td_md5;
374 digest_hd_st td_sha;
375 gnutls_datum_t dconcat;
376 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
378 ret = _gnutls_hash_copy (&td_md5, &session->internals.handshake_mac_handle_md5);
379 if (ret < 0)
381 gnutls_assert ();
382 return ret;
385 ret = _gnutls_hash_copy (&td_sha, &session->internals.handshake_mac_handle_sha);
386 if (ret < 0)
388 gnutls_assert ();
389 _gnutls_hash_deinit (&td_md5, NULL);
390 return GNUTLS_E_HASH_FAILED;
393 if (ver == GNUTLS_SSL3)
395 ret = _gnutls_generate_master (session, 1);
396 if (ret < 0)
398 gnutls_assert ();
399 return ret;
402 _gnutls_mac_deinit_ssl3_handshake (&td_md5, concat,
403 session->security_parameters.
404 master_secret, TLS_MASTER_SIZE);
405 _gnutls_mac_deinit_ssl3_handshake (&td_sha, &concat[16],
406 session->security_parameters.
407 master_secret, TLS_MASTER_SIZE);
409 else
411 _gnutls_hash_deinit (&td_md5, concat);
412 _gnutls_hash_deinit (&td_sha, &concat[16]);
415 dconcat.data = concat;
416 dconcat.size = 20 + 16; /* md5+ sha */
418 ret = _gnutls_verify_sig (cert, &dconcat, signature, 16);
419 if (ret < 0)
421 gnutls_assert ();
422 return ret;
425 return ret;
429 /* Generates a signature of all the random data and the parameters.
430 * Used in DHE_* ciphersuites.
433 _gnutls_verify_sig_params (gnutls_session_t session, gnutls_cert * cert,
434 const gnutls_datum_t * params,
435 gnutls_datum_t * signature)
437 gnutls_datum_t dconcat;
438 int ret;
439 digest_hd_st td_md5;
440 digest_hd_st td_sha;
441 opaque concat[36];
442 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
444 if (ver < GNUTLS_TLS1_2)
446 ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
447 if (ret < 0)
449 gnutls_assert ();
450 return ret;
453 _gnutls_hash (&td_md5, session->security_parameters.client_random,
454 TLS_RANDOM_SIZE);
455 _gnutls_hash (&td_md5, session->security_parameters.server_random,
456 TLS_RANDOM_SIZE);
457 _gnutls_hash (&td_md5, params->data, params->size);
460 ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1);
461 if (ret < 0)
463 gnutls_assert ();
464 if (ver < GNUTLS_TLS1_2)
465 _gnutls_hash_deinit (&td_md5, NULL);
466 return ret;
469 _gnutls_hash (&td_sha, session->security_parameters.client_random,
470 TLS_RANDOM_SIZE);
471 _gnutls_hash (&td_sha, session->security_parameters.server_random,
472 TLS_RANDOM_SIZE);
473 _gnutls_hash (&td_sha, params->data, params->size);
475 if (ver < GNUTLS_TLS1_2)
477 _gnutls_hash_deinit (&td_md5, concat);
478 _gnutls_hash_deinit (&td_sha, &concat[16]);
479 dconcat.size = 36;
481 else
483 #if 1
484 /* Use NULL parameters. */
485 memcpy (concat,
486 "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
487 15);
488 _gnutls_hash_deinit (&td_sha, &concat[15]);
489 dconcat.size = 35;
490 #else
491 /* No parameters field. */
492 memcpy (concat,
493 "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14",
494 13);
495 _gnutls_hash_deinit (&td_sha, &concat[13]);
496 dconcat.size = 33;
497 #endif
500 dconcat.data = concat;
502 ret = _gnutls_verify_sig (cert, &dconcat, signature, dconcat.size - 20);
503 if (ret < 0)
505 gnutls_assert ();
506 return ret;
509 return ret;