corrected copyright notices
[gnutls.git] / lib / ext / signature.c
blobd8a6bccac0498738add913ad74922a31de7e7669
1 /*
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS 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 3 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 License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* This file contains the code the Certificate Type TLS extension.
24 * This extension is currently gnutls specific.
27 #include "gnutls_int.h"
28 #include "gnutls_errors.h"
29 #include "gnutls_num.h"
30 #include <gnutls/gnutls.h>
31 #include <ext/signature.h>
32 #include <gnutls_state.h>
33 #include <gnutls_num.h>
34 #include <algorithms.h>
35 #include <abstract_int.h>
37 static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
38 const uint8_t * data,
39 size_t data_size);
40 static int _gnutls_signature_algorithm_send_params (gnutls_session_t session,
41 gnutls_buffer_st * extdata);
42 static void signature_algorithms_deinit_data (extension_priv_data_t priv);
43 static int signature_algorithms_pack (extension_priv_data_t epriv,
44 gnutls_buffer_st * ps);
45 static int signature_algorithms_unpack (gnutls_buffer_st * ps,
46 extension_priv_data_t * _priv);
48 extension_entry_st ext_mod_sig = {
49 .name = "SIGNATURE ALGORITHMS",
50 .type = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
51 .parse_type = GNUTLS_EXT_TLS,
53 .recv_func = _gnutls_signature_algorithm_recv_params,
54 .send_func = _gnutls_signature_algorithm_send_params,
55 .pack_func = signature_algorithms_pack,
56 .unpack_func = signature_algorithms_unpack,
57 .deinit_func = signature_algorithms_deinit_data,
60 typedef struct
62 /* TLS 1.2 signature algorithms */
63 gnutls_sign_algorithm_t sign_algorithms[MAX_SIGNATURE_ALGORITHMS];
64 uint16_t sign_algorithms_size;
65 } sig_ext_st;
67 /* generates a SignatureAndHashAlgorithm structure with length as prefix
68 * by using the setup priorities.
70 int
71 _gnutls_sign_algorithm_write_params (gnutls_session_t session, uint8_t * data,
72 size_t max_data_size)
74 uint8_t *p = data, *len_p;
75 unsigned int len, i, j;
76 const sign_algorithm_st *aid;
78 if (max_data_size < (session->internals.priorities.sign_algo.algorithms*2) + 2)
80 gnutls_assert ();
81 return GNUTLS_E_SHORT_MEMORY_BUFFER;
84 len = 0;
85 len_p = p;
87 p += 2;
89 for (i = j = 0; j < session->internals.priorities.sign_algo.algorithms; i += 2, j++)
91 aid =
92 _gnutls_sign_to_tls_aid (session->internals.priorities.
93 sign_algo.priority[j]);
95 if (aid == NULL)
96 continue;
98 _gnutls_handshake_log ("EXT[%p]: sent signature algo (%d.%d) %s\n", session, aid->hash_algorithm,
99 aid->sign_algorithm, gnutls_sign_get_name(session->internals.priorities.sign_algo.priority[j]));
100 *p = aid->hash_algorithm;
101 p++;
102 *p = aid->sign_algorithm;
103 p++;
104 len+=2;
107 _gnutls_write_uint16 (len, len_p);
108 return len + 2;
112 /* Parses the Signature Algorithm structure and stores data into
113 * session->security_parameters.extensions.
116 _gnutls_sign_algorithm_parse_data (gnutls_session_t session,
117 const uint8_t * data, size_t data_size)
119 unsigned int sig, i;
120 sig_ext_st *priv;
121 extension_priv_data_t epriv;
123 priv = gnutls_calloc (1, sizeof (*priv));
124 if (priv == NULL)
126 gnutls_assert ();
127 return GNUTLS_E_MEMORY_ERROR;
130 for (i = 0; i < data_size; i += 2)
132 sign_algorithm_st aid;
134 aid.hash_algorithm = data[i];
135 aid.sign_algorithm = data[i + 1];
137 sig = _gnutls_tls_aid_to_sign (&aid);
139 _gnutls_handshake_log ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session, aid.hash_algorithm,
140 aid.sign_algorithm, gnutls_sign_get_name(sig));
142 if (sig != GNUTLS_SIGN_UNKNOWN)
144 priv->sign_algorithms[priv->sign_algorithms_size++] = sig;
145 if (priv->sign_algorithms_size == MAX_SIGNATURE_ALGORITHMS)
146 break;
150 epriv.ptr = priv;
151 _gnutls_ext_set_session_data (session,
152 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, epriv);
154 return 0;
158 * In case of a server: if a SIGNATURE_ALGORITHMS extension type is
159 * received then it stores into the session security parameters the
160 * new value.
162 * In case of a client: If a signature_algorithms have been specified
163 * then it is an error;
166 static int
167 _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
168 const uint8_t * data,
169 size_t _data_size)
171 ssize_t data_size = _data_size;
172 int ret;
174 if (session->security_parameters.entity == GNUTLS_CLIENT)
176 /* nothing for now */
177 gnutls_assert ();
178 /* Although TLS 1.2 mandates that we must not accept reply
179 * to this message, there are good reasons to just ignore it. Check
180 * http://www.ietf.org/mail-archive/web/tls/current/msg03880.html
182 /* return GNUTLS_E_UNEXPECTED_PACKET; */
184 else
186 /* SERVER SIDE - we must check if the sent cert type is the right one
188 if (data_size > 2)
190 uint16_t len;
192 DECR_LEN (data_size, 2);
193 len = _gnutls_read_uint16 (data);
194 DECR_LEN (data_size, len);
196 ret = _gnutls_sign_algorithm_parse_data (session, data + 2, len);
197 if (ret < 0)
199 gnutls_assert ();
200 return ret;
205 return 0;
208 /* returns data_size or a negative number on failure
210 static int
211 _gnutls_signature_algorithm_send_params (gnutls_session_t session,
212 gnutls_buffer_st* extdata)
214 int ret;
215 size_t init_length = extdata->length;
216 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
218 /* this function sends the client extension data */
219 if (session->security_parameters.entity == GNUTLS_CLIENT
220 && _gnutls_version_has_selectable_sighash (ver))
222 if (session->internals.priorities.sign_algo.algorithms > 0)
224 uint8_t p[MAX_SIGN_ALGO_SIZE];
226 ret =
227 _gnutls_sign_algorithm_write_params (session, p, sizeof(p));
228 if (ret < 0)
229 return gnutls_assert_val(ret);
231 ret = _gnutls_buffer_append_data(extdata, p, ret);
232 if (ret < 0)
233 return gnutls_assert_val(ret);
235 return extdata->length - init_length;
239 /* if we are here it means we don't send the extension */
240 return 0;
243 /* Returns a requested by the peer signature algorithm that
244 * matches the given certificate's public key algorithm.
246 gnutls_sign_algorithm_t
247 _gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_pcert_st* cert)
249 unsigned i;
250 int ret;
251 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
252 sig_ext_st *priv;
253 extension_priv_data_t epriv;
254 unsigned int cert_algo;
256 cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
258 ret =
259 _gnutls_ext_get_session_data (session,
260 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
261 &epriv);
262 priv = epriv.ptr;
264 if (ret < 0 || !_gnutls_version_has_selectable_sighash (ver)
265 || priv->sign_algorithms_size == 0)
266 /* none set, allow SHA-1 only */
268 return gnutls_pk_to_sign (cert_algo, GNUTLS_DIG_SHA1);
271 for (i = 0; i < priv->sign_algorithms_size; i++)
273 if (gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == cert_algo)
275 if (_gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, priv->sign_algorithms[i]) < 0)
276 continue;
278 if (_gnutls_session_sign_algo_enabled(session, priv->sign_algorithms[i]) < 0)
279 continue;
281 return priv->sign_algorithms[i];
285 return GNUTLS_SIGN_UNKNOWN;
288 /* Check if the given signature algorithm is supported.
289 * This means that it is enabled by the priority functions,
290 * and in case of a server a matching certificate exists.
293 _gnutls_session_sign_algo_enabled (gnutls_session_t session,
294 gnutls_sign_algorithm_t sig)
296 unsigned i;
297 int ret;
298 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
299 sig_ext_st *priv;
300 extension_priv_data_t epriv;
302 ret =
303 _gnutls_ext_get_session_data (session,
304 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
305 &epriv);
306 if (ret < 0)
308 gnutls_assert ();
309 return 0;
311 priv = epriv.ptr;
313 if (!_gnutls_version_has_selectable_sighash (ver)
314 || priv->sign_algorithms_size == 0)
315 /* none set, allow all */
317 return 0;
320 for (i = 0; i < session->internals.priorities.sign_algo.algorithms; i++)
322 if (session->internals.priorities.sign_algo.priority[i] == sig)
324 return 0; /* ok */
328 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
331 static void
332 signature_algorithms_deinit_data (extension_priv_data_t priv)
334 gnutls_free (priv.ptr);
337 static int
338 signature_algorithms_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
340 sig_ext_st *priv = epriv.ptr;
341 int ret, i;
343 BUFFER_APPEND_NUM (ps, priv->sign_algorithms_size);
344 for (i = 0; i < priv->sign_algorithms_size; i++)
346 BUFFER_APPEND_NUM (ps, priv->sign_algorithms[i]);
348 return 0;
351 static int
352 signature_algorithms_unpack (gnutls_buffer_st * ps,
353 extension_priv_data_t * _priv)
355 sig_ext_st *priv;
356 int i, ret;
357 extension_priv_data_t epriv;
359 priv = gnutls_calloc (1, sizeof (*priv));
360 if (priv == NULL)
362 gnutls_assert ();
363 return GNUTLS_E_MEMORY_ERROR;
366 BUFFER_POP_NUM (ps, priv->sign_algorithms_size);
367 for (i = 0; i < priv->sign_algorithms_size; i++)
369 BUFFER_POP_NUM (ps, priv->sign_algorithms[i]);
372 epriv.ptr = priv;
373 *_priv = epriv;
375 return 0;
377 error:
378 gnutls_free (priv);
379 return ret;
385 * gnutls_sign_algorithm_get_requested:
386 * @session: is a #gnutls_session_t structure.
387 * @indx: is an index of the signature algorithm to return
388 * @algo: the returned certificate type will be stored there
390 * Returns the signature algorithm specified by index that was
391 * requested by the peer. If the specified index has no data available
392 * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If
393 * the negotiated TLS version does not support signature algorithms
394 * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
395 * for the first index. The first index is 0.
397 * This function is useful in the certificate callback functions
398 * to assist in selecting the correct certificate.
400 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
401 * an error code is returned.
403 * Since: 2.10.0
406 gnutls_sign_algorithm_get_requested (gnutls_session_t session,
407 size_t indx,
408 gnutls_sign_algorithm_t * algo)
410 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
411 sig_ext_st *priv;
412 extension_priv_data_t epriv;
413 int ret;
415 ret =
416 _gnutls_ext_get_session_data (session,
417 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
418 &epriv);
419 if (ret < 0)
421 gnutls_assert ();
422 return ret;
424 priv = epriv.ptr;
426 if (!_gnutls_version_has_selectable_sighash (ver)
427 || priv->sign_algorithms_size == 0)
429 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
432 if (indx < priv->sign_algorithms_size)
434 *algo = priv->sign_algorithms[indx];
435 return 0;
437 else
438 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
442 * gnutls_sign_algorithm_get:
443 * @session: is a #gnutls_session_t structure.
445 * Returns the signature algorithm that is (or will be) used in this
446 * session to sign data.
448 * Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN.
450 * Since: 3.1.1
453 gnutls_sign_algorithm_get (gnutls_session_t session)
455 return session->security_parameters.sign_algo;