Honor uninitialized private key in destructor
[gnutls.git] / lib / ext_signature.c
blob48eb5358e3000e1497bb6b94a4faf088da7ca5d1
1 /*
2 * Copyright (C) 2002,2003,2004,2005,2009,2010,2011 Free Software
3 * Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA
26 /* This file contains the code the Certificate Type TLS extension.
27 * This extension is currently gnutls specific.
30 #include "gnutls_int.h"
31 #include "gnutls_errors.h"
32 #include "gnutls_num.h"
33 #include <ext_signature.h>
34 #include <gnutls_state.h>
35 #include <gnutls_num.h>
36 #include <gnutls_algorithms.h>
37 #include <x509/common.h> /* dsa_q_to_hash */
38 #include <gnutls_cert.h>
40 static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
41 const opaque * data,
42 size_t data_size);
43 static int _gnutls_signature_algorithm_send_params (gnutls_session_t session,
44 opaque * data, size_t);
45 static void signature_algorithms_deinit_data (extension_priv_data_t priv);
46 static int signature_algorithms_pack (extension_priv_data_t epriv,
47 gnutls_buffer_st * ps);
48 static int signature_algorithms_unpack (gnutls_buffer_st * ps,
49 extension_priv_data_t * _priv);
51 extension_entry_st ext_mod_sig = {
52 .name = "SIGNATURE ALGORITHMS",
53 .type = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
54 .parse_type = GNUTLS_EXT_TLS,
56 .recv_func = _gnutls_signature_algorithm_recv_params,
57 .send_func = _gnutls_signature_algorithm_send_params,
58 .pack_func = signature_algorithms_pack,
59 .unpack_func = signature_algorithms_unpack,
60 .deinit_func = signature_algorithms_deinit_data,
63 typedef struct
65 /* TLS 1.2 signature algorithms */
66 gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS];
67 uint16_t sign_algorithms_size;
68 } sig_ext_st;
70 /* generates a SignatureAndHashAlgorithm structure with length as prefix
71 * by using the setup priorities.
73 int
74 _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data,
75 size_t max_data_size)
77 opaque *p = data, *len_p;
78 int len, i, j, hash;
79 const sign_algorithm_st *aid;
81 if (max_data_size < (session->internals.priorities.sign_algo.algorithms*2) + 2)
83 gnutls_assert ();
84 return GNUTLS_E_SHORT_MEMORY_BUFFER;
87 len = 0;
88 len_p = p;
90 p += 2;
92 for (i = j = 0; j < session->internals.priorities.sign_algo.algorithms; i += 2, j++)
94 /* In gnutls we keep a state of SHA1 and SHA256 and thus cannot
95 * use anything else.
97 hash = _gnutls_sign_get_hash_algorithm(session->internals.priorities.sign_algo.priority[j]);
98 if (hash != GNUTLS_DIG_SHA1 && hash != GNUTLS_DIG_SHA256)
99 continue;
101 aid =
102 _gnutls_sign_to_tls_aid (session->internals.priorities.
103 sign_algo.priority[j]);
105 if (aid == NULL)
106 continue;
108 _gnutls_debug_log ("EXT[SIGA]: sent signature algo (%d.%d) %s\n", aid->hash_algorithm,
109 aid->sign_algorithm, gnutls_sign_get_name(session->internals.priorities.sign_algo.priority[j]));
110 *p = aid->hash_algorithm;
111 p++;
112 *p = aid->sign_algorithm;
113 p++;
114 len+=2;
117 _gnutls_write_uint16 (len, len_p);
119 return len + 2;
123 /* Parses the Signature Algorithm structure and stores data into
124 * session->security_parameters.extensions.
127 _gnutls_sign_algorithm_parse_data (gnutls_session_t session,
128 const opaque * data, size_t data_size)
130 int sig, i;
131 sig_ext_st *priv;
132 extension_priv_data_t epriv;
134 priv = gnutls_calloc (1, sizeof (*priv));
135 if (priv == NULL)
137 gnutls_assert ();
138 return GNUTLS_E_MEMORY_ERROR;
141 for (i = 0; i < data_size; i += 2)
143 sign_algorithm_st aid;
145 aid.hash_algorithm = data[i];
146 aid.sign_algorithm = data[i + 1];
148 sig = _gnutls_tls_aid_to_sign (&aid);
150 _gnutls_debug_log ("EXT[SIGA]: rcvd signature algo (%d.%d) %s\n", aid.hash_algorithm,
151 aid.sign_algorithm, gnutls_sign_get_name(sig));
153 if (sig != GNUTLS_SIGN_UNKNOWN)
155 priv->sign_algorithms[priv->sign_algorithms_size++] = sig;
156 if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS)
157 break;
161 epriv.ptr = priv;
162 _gnutls_ext_set_session_data (session,
163 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv);
165 return 0;
169 * In case of a server: if a SIGNATURE_ALGORITHMS extension type is
170 * received then it stores into the session security parameters the
171 * new value.
173 * In case of a client: If a signature_algorithms have been specified
174 * then it is an error;
177 static int
178 _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
179 const opaque * data,
180 size_t _data_size)
182 ssize_t data_size = _data_size;
183 int ret;
185 if (session->security_parameters.entity == GNUTLS_CLIENT)
187 /* nothing for now */
188 gnutls_assert ();
189 /* Although TLS 1.2 mandates that we must not accept reply
190 * to this message, there are good reasons to just ignore it. Check
191 * http://www.ietf.org/mail-archive/web/tls/current/msg03880.html
193 /* return GNUTLS_E_UNEXPECTED_PACKET; */
195 else
197 /* SERVER SIDE - we must check if the sent cert type is the right one
199 if (data_size > 2)
201 uint16_t len;
203 DECR_LEN (data_size, 2);
204 len = _gnutls_read_uint16 (data);
205 DECR_LEN (data_size, len);
207 ret = _gnutls_sign_algorithm_parse_data (session, data + 2, len);
208 if (ret < 0)
210 gnutls_assert ();
211 return ret;
216 return 0;
219 /* returns data_size or a negative number on failure
221 static int
222 _gnutls_signature_algorithm_send_params (gnutls_session_t session,
223 opaque * data, size_t data_size)
225 int ret;
226 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
228 /* this function sends the client extension data */
229 if (session->security_parameters.entity == GNUTLS_CLIENT
230 && _gnutls_version_has_selectable_sighash (ver))
232 if (session->internals.priorities.sign_algo.algorithms > 0)
234 ret =
235 _gnutls_sign_algorithm_write_params (session, data, data_size);
236 if (ret < 0)
238 gnutls_assert ();
239 return ret;
241 return ret;
245 /* if we are here it means we don't send the extension */
246 return 0;
249 int cert_compatible_with_sig(gnutls_cert* cert, gnutls_protocol_t ver,
250 gnutls_sign_algorithm_t sign)
252 unsigned int hash_len;
254 if (cert->subject_pk_algorithm == GNUTLS_PK_DSA)
255 { /* override */
256 int hash_algo = _gnutls_dsa_q_to_hash (cert->params[1], &hash_len);
258 /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
259 if (!_gnutls_version_has_selectable_sighash (ver))
261 if (hash_algo != GNUTLS_DIG_SHA1)
262 return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
264 else
266 if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) < hash_len)
267 return GNUTLS_E_UNWANTED_ALGORITHM;
272 return 0;
275 /* Returns a requested by the peer signature algorithm that
276 * matches the given public key algorithm. Index can be increased
277 * to return the second choice etc.
279 gnutls_sign_algorithm_t
280 _gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_cert* cert)
282 unsigned i;
283 int ret;
284 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
285 sig_ext_st *priv;
286 extension_priv_data_t epriv;
288 ret =
289 _gnutls_ext_get_session_data (session,
290 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
291 &epriv);
292 priv = epriv.ptr;
294 if (ret < 0 || !_gnutls_version_has_selectable_sighash (ver)
295 || priv->sign_algorithms_size == 0)
296 /* none set, allow SHA-1 only */
298 return _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, GNUTLS_DIG_SHA1);
301 for (i = 0; i < priv->sign_algorithms_size; i++)
303 if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == cert->subject_pk_algorithm)
305 if (cert_compatible_with_sig(cert, ver, priv->sign_algorithms[i]) < 0)
306 continue;
308 return priv->sign_algorithms[i];
312 return GNUTLS_SIGN_UNKNOWN;
316 /* Check if the given signature algorithm is accepted by
317 * the peer. Returns 0 on success or a negative value
318 * on error.
321 _gnutls_session_sign_algo_requested (gnutls_session_t session,
322 gnutls_sign_algorithm_t sig)
324 unsigned i;
325 int ret, hash;
326 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
327 sig_ext_st *priv;
328 extension_priv_data_t epriv;
330 if (!_gnutls_version_has_selectable_sighash (ver))
332 return 0;
335 ret =
336 _gnutls_ext_get_session_data (session,
337 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
338 &epriv);
339 if (ret < 0)
341 gnutls_assert ();
342 /* extension not received allow SHA1 and SHA256 */
343 hash = _gnutls_sign_get_hash_algorithm (sig);
344 if (hash == GNUTLS_DIG_SHA1 || hash == GNUTLS_DIG_SHA256)
345 return 0;
346 else
347 return ret;
349 priv = epriv.ptr;
351 if (priv->sign_algorithms_size == 0)
352 /* none set, allow all */
354 return 0;
357 for (i = 0; i < priv->sign_algorithms_size; i++)
359 if (priv->sign_algorithms[i] == sig)
361 return 0; /* ok */
365 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
368 /* Check if the given signature algorithm is supported.
369 * This means that it is enabled by the priority functions,
370 * and in case of a server a matching certificate exists.
373 _gnutls_session_sign_algo_enabled (gnutls_session_t session,
374 gnutls_sign_algorithm_t sig)
376 unsigned i;
377 int ret;
378 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
379 sig_ext_st *priv;
380 extension_priv_data_t epriv;
382 ret =
383 _gnutls_ext_get_session_data (session,
384 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
385 &epriv);
386 if (ret < 0)
388 gnutls_assert ();
389 return 0;
391 priv = epriv.ptr;
393 if (!_gnutls_version_has_selectable_sighash (ver)
394 || priv->sign_algorithms_size == 0)
395 /* none set, allow all */
397 return 0;
400 for (i = 0; i < session->internals.priorities.sign_algo.algorithms; i++)
402 if (session->internals.priorities.sign_algo.priority[i] == sig)
404 return 0; /* ok */
408 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
411 static void
412 signature_algorithms_deinit_data (extension_priv_data_t priv)
414 gnutls_free (priv.ptr);
417 static int
418 signature_algorithms_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
420 sig_ext_st *priv = epriv.ptr;
421 int ret, i;
423 BUFFER_APPEND_NUM (ps, priv->sign_algorithms_size);
424 for (i = 0; i < priv->sign_algorithms_size; i++)
426 BUFFER_APPEND_NUM (ps, priv->sign_algorithms[i]);
428 return 0;
431 static int
432 signature_algorithms_unpack (gnutls_buffer_st * ps,
433 extension_priv_data_t * _priv)
435 sig_ext_st *priv;
436 int i, ret;
437 extension_priv_data_t epriv;
439 priv = gnutls_calloc (1, sizeof (*priv));
440 if (priv == NULL)
442 gnutls_assert ();
443 return GNUTLS_E_MEMORY_ERROR;
446 BUFFER_POP_NUM (ps, priv->sign_algorithms_size);
447 for (i = 0; i < priv->sign_algorithms_size; i++)
449 BUFFER_POP_NUM (ps, priv->sign_algorithms[i]);
452 epriv.ptr = priv;
453 *_priv = epriv;
455 return 0;
457 error:
458 gnutls_free (priv);
459 return ret;
465 * gnutls_sign_algorithm_get_requested:
466 * @session: is a #gnutls_session_t structure.
467 * @indx: is an index of the signature algorithm to return
468 * @algo: the returned certificate type will be stored there
470 * Returns the signature algorithm specified by index that was
471 * requested by the peer. If the specified index has no data available
472 * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If
473 * the negotiated TLS version does not support signature algorithms
474 * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
475 * for the first index. The first index is 0.
477 * This function is useful in the certificate callback functions
478 * to assist in selecting the correct certificate.
480 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
481 * an error code is returned.
483 * Since: 2.10.0
486 gnutls_sign_algorithm_get_requested (gnutls_session_t session,
487 size_t indx,
488 gnutls_sign_algorithm_t * algo)
490 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
491 sig_ext_st *priv;
492 extension_priv_data_t epriv;
493 int ret;
495 ret =
496 _gnutls_ext_get_session_data (session,
497 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
498 &epriv);
499 if (ret < 0)
501 gnutls_assert ();
502 return ret;
504 priv = epriv.ptr;
506 if (!_gnutls_version_has_selectable_sighash (ver)
507 || priv->sign_algorithms_size == 0)
509 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
512 if (indx < priv->sign_algorithms_size)
514 *algo = priv->sign_algorithms[indx];
515 return 0;
517 else
518 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;