2 * Copyright (C) 2002,2003,2004,2005,2009,2010,2011 Free Software
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,
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,
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,
65 /* TLS 1.2 signature algorithms */
66 gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS];
67 uint16_t sign_algorithms_size;
70 /* generates a SignatureAndHashAlgorithm structure with length as prefix
71 * by using the setup priorities.
74 _gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data,
77 opaque *p = data, *len_p;
79 const sign_algorithm_st *aid;
81 if (max_data_size < (session->internals.priorities.sign_algo.algorithms*2) + 2)
84 return GNUTLS_E_SHORT_MEMORY_BUFFER;
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
97 hash = _gnutls_sign_get_hash_algorithm(session->internals.priorities.sign_algo.priority[j]);
98 if (hash != GNUTLS_DIG_SHA1 && hash != GNUTLS_DIG_SHA256)
102 _gnutls_sign_to_tls_aid (session->internals.priorities.
103 sign_algo.priority[j]);
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;
112 *p = aid->sign_algorithm;
117 _gnutls_write_uint16 (len, len_p);
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)
132 extension_priv_data_t epriv;
134 priv = gnutls_calloc (1, sizeof (*priv));
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));
154 if (sig != GNUTLS_SIGN_UNKNOWN)
156 hash = _gnutls_sign_get_hash_algorithm(sig);
157 if (hash != GNUTLS_DIG_SHA1 && hash != GNUTLS_DIG_SHA256)
160 priv->sign_algorithms[priv->sign_algorithms_size++] = sig;
161 if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS)
167 _gnutls_ext_set_session_data (session,
168 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv);
174 * In case of a server: if a SIGNATURE_ALGORITHMS extension type is
175 * received then it stores into the session security parameters the
178 * In case of a client: If a signature_algorithms have been specified
179 * then it is an error;
183 _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
187 ssize_t data_size = _data_size;
190 if (session->security_parameters.entity == GNUTLS_CLIENT)
192 /* nothing for now */
194 /* Although TLS 1.2 mandates that we must not accept reply
195 * to this message, there are good reasons to just ignore it. Check
196 * http://www.ietf.org/mail-archive/web/tls/current/msg03880.html
198 /* return GNUTLS_E_UNEXPECTED_PACKET; */
202 /* SERVER SIDE - we must check if the sent cert type is the right one
208 DECR_LEN (data_size, 2);
209 len = _gnutls_read_uint16 (data);
210 DECR_LEN (data_size, len);
212 ret = _gnutls_sign_algorithm_parse_data (session, data + 2, len);
224 /* returns data_size or a negative number on failure
227 _gnutls_signature_algorithm_send_params (gnutls_session_t session,
228 opaque * data, size_t data_size)
231 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
233 /* this function sends the client extension data */
234 if (session->security_parameters.entity == GNUTLS_CLIENT
235 && _gnutls_version_has_selectable_sighash (ver))
237 if (session->internals.priorities.sign_algo.algorithms > 0)
240 _gnutls_sign_algorithm_write_params (session, data, data_size);
250 /* if we are here it means we don't send the extension */
254 int cert_compatible_with_sig(gnutls_cert* cert, gnutls_protocol_t ver,
255 gnutls_sign_algorithm_t sign)
257 unsigned int hash_len;
259 if (cert->subject_pk_algorithm == GNUTLS_PK_DSA)
261 int hash_algo = _gnutls_dsa_q_to_hash (cert->params[1], &hash_len);
263 /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
264 if (!_gnutls_version_has_selectable_sighash (ver))
266 if (hash_algo != GNUTLS_DIG_SHA1)
267 return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
271 if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) < hash_len)
272 return GNUTLS_E_UNWANTED_ALGORITHM;
280 /* Returns a requested by the peer signature algorithm that
281 * matches the given public key algorithm. Index can be increased
282 * to return the second choice etc.
284 gnutls_sign_algorithm_t
285 _gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_cert* cert)
289 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
291 extension_priv_data_t epriv;
294 _gnutls_ext_get_session_data (session,
295 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
299 if (ret < 0 || !_gnutls_version_has_selectable_sighash (ver)
300 || priv->sign_algorithms_size == 0)
301 /* none set, allow SHA-1 only */
303 return _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, GNUTLS_DIG_SHA1);
306 for (i = 0; i < priv->sign_algorithms_size; i++)
308 if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == cert->subject_pk_algorithm)
310 if (cert_compatible_with_sig(cert, ver, priv->sign_algorithms[i]) < 0)
313 return priv->sign_algorithms[i];
317 return GNUTLS_SIGN_UNKNOWN;
321 /* Check if the given signature algorithm is accepted by
322 * the peer. Returns 0 on success or a negative value
326 _gnutls_session_sign_algo_requested (gnutls_session_t session,
327 gnutls_sign_algorithm_t sig)
331 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
333 extension_priv_data_t epriv;
335 if (!_gnutls_version_has_selectable_sighash (ver))
341 _gnutls_ext_get_session_data (session,
342 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
347 /* extension not received allow SHA1 and SHA256 */
348 hash = _gnutls_sign_get_hash_algorithm (sig);
349 if (hash == GNUTLS_DIG_SHA1 || hash == GNUTLS_DIG_SHA256)
356 if (priv->sign_algorithms_size == 0)
357 /* none set, allow all */
362 for (i = 0; i < priv->sign_algorithms_size; i++)
364 if (priv->sign_algorithms[i] == sig)
370 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
373 /* Check if the given signature algorithm is supported.
374 * This means that it is enabled by the priority functions,
375 * and in case of a server a matching certificate exists.
378 _gnutls_session_sign_algo_enabled (gnutls_session_t session,
379 gnutls_sign_algorithm_t sig)
383 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
385 extension_priv_data_t epriv;
388 _gnutls_ext_get_session_data (session,
389 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
398 if (!_gnutls_version_has_selectable_sighash (ver)
399 || priv->sign_algorithms_size == 0)
400 /* none set, allow all */
405 for (i = 0; i < session->internals.priorities.sign_algo.algorithms; i++)
407 if (session->internals.priorities.sign_algo.priority[i] == sig)
413 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
417 signature_algorithms_deinit_data (extension_priv_data_t priv)
419 gnutls_free (priv.ptr);
423 signature_algorithms_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
425 sig_ext_st *priv = epriv.ptr;
428 BUFFER_APPEND_NUM (ps, priv->sign_algorithms_size);
429 for (i = 0; i < priv->sign_algorithms_size; i++)
431 BUFFER_APPEND_NUM (ps, priv->sign_algorithms[i]);
437 signature_algorithms_unpack (gnutls_buffer_st * ps,
438 extension_priv_data_t * _priv)
442 extension_priv_data_t epriv;
444 priv = gnutls_calloc (1, sizeof (*priv));
448 return GNUTLS_E_MEMORY_ERROR;
451 BUFFER_POP_NUM (ps, priv->sign_algorithms_size);
452 for (i = 0; i < priv->sign_algorithms_size; i++)
454 BUFFER_POP_NUM (ps, priv->sign_algorithms[i]);
470 * gnutls_sign_algorithm_get_requested:
471 * @session: is a #gnutls_session_t structure.
472 * @indx: is an index of the signature algorithm to return
473 * @algo: the returned certificate type will be stored there
475 * Returns the signature algorithm specified by index that was
476 * requested by the peer. If the specified index has no data available
477 * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If
478 * the negotiated TLS version does not support signature algorithms
479 * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
480 * for the first index. The first index is 0.
482 * This function is useful in the certificate callback functions
483 * to assist in selecting the correct certificate.
485 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
486 * an error code is returned.
491 gnutls_sign_algorithm_get_requested (gnutls_session_t session,
493 gnutls_sign_algorithm_t * algo)
495 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
497 extension_priv_data_t epriv;
501 _gnutls_ext_get_session_data (session,
502 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
511 if (!_gnutls_version_has_selectable_sighash (ver)
512 || priv->sign_algorithms_size == 0)
514 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
517 if (indx < priv->sign_algorithms_size)
519 *algo = priv->sign_algorithms[indx];
523 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;