Sync with TP.
[gnutls.git] / lib / ext_signature.c
blobcd12fc71de75486462685374da39d3fc3f433d6f
1 /*
2 * Copyright (C) 2002, 2003, 2004, 2005 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 /* This file contains the code the Certificate Type TLS extension.
26 * This extension is currently gnutls specific.
29 #include "gnutls_int.h"
30 #include "gnutls_errors.h"
31 #include "gnutls_num.h"
32 #include <ext_signature.h>
33 #include <gnutls_state.h>
34 #include <gnutls_num.h>
35 #include <gnutls_algorithms.h>
37 /* generates a SignatureAndHashAlgorithm structure with length as prefix
38 * by using the setup priorities.
40 int _gnutls_sign_algorithm_write_params(gnutls_session_t session, opaque *data, size_t max_data_size)
42 opaque* p = data;
43 int len, i ,j;
44 int ret;
45 sign_algorithm_st aid;
47 len = session->internals.priorities.sign_algo.algorithms * 2;
48 if (max_data_size < len + 2)
50 gnutls_assert ();
51 return GNUTLS_E_SHORT_MEMORY_BUFFER;
54 _gnutls_write_uint16 (len, p);
55 p += 2;
57 for (i = j = 0; i < len; i += 2, j++)
59 aid = _gnutls_sign_to_tls_aid(session->internals.priorities.sign_algo.priority[j]);
60 *p = aid.hash_algorithm;
61 p++;
62 *p = aid.sign_algorithm;
63 p++;
66 return len + 2;
69 /* Parses the Signature Algorithm structure and stores data into
70 * session->security_parameters.extensions.
72 int
73 _gnutls_sign_algorithm_parse_data (gnutls_session_t session, const opaque * data,
74 size_t data_size)
76 int sig, i;
78 session->security_parameters.extensions.sign_algorithms_size = 0;
80 for (i = 0; i < data_size; i += 2)
82 sign_algorithm_st aid;
84 aid.hash_algorithm = data[i];
85 aid.sign_algorithm = data[i+1];
87 sig = _gnutls_tls_aid_to_sign(&aid);
88 if (sig != GNUTLS_SIGN_UNKNOWN)
90 session->security_parameters.extensions.sign_algorithms[session->
91 security_parameters.extensions.
92 sign_algorithms_size++]
93 = sig;
94 if (session->security_parameters.extensions.sign_algorithms_size ==
95 MAX_SIGNATURE_ALGORITHMS)
96 break;
100 return 0;
104 * In case of a server: if a SIGNATURE_ALGORITHMS extension type is received then it stores
105 * into the session security parameters the new value.
107 * In case of a client: If a signature_algorithms have been specified then it is an error;
112 _gnutls_signature_algorithm_recv_params (gnutls_session_t session,
113 const opaque * data,
114 size_t _data_size)
116 ssize_t data_size = _data_size;
117 int ret;
119 if (session->security_parameters.entity == GNUTLS_CLIENT)
121 /* nothing for now */
122 gnutls_assert ();
123 /* Although TLS 1.2 mandates that we must not accept reply
124 * to this message, there are good reasons to just ignore it. Check
125 * http://www.ietf.org/mail-archive/web/tls/current/msg03880.html
127 /* return GNUTLS_E_UNEXPECTED_PACKET; */
129 else
131 /* SERVER SIDE - we must check if the sent cert type is the right one
133 if (data_size > 2)
135 uint16_t len;
138 DECR_LEN (data_size, 2);
139 len = _gnutls_read_uint16 (data);
140 DECR_LEN (data_size, len);
142 ret = _gnutls_sign_algorithm_parse_data (session, data + 2, len);
143 if (ret < 0)
145 gnutls_assert();
146 return ret;
151 return 0;
154 /* returns data_size or a negative number on failure
157 _gnutls_signature_algorithm_send_params (gnutls_session_t session,
158 opaque * data, size_t data_size)
160 int ret;
161 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
163 /* this function sends the client extension data */
164 if (session->security_parameters.entity == GNUTLS_CLIENT
165 && _gnutls_version_has_selectable_sighash (ver))
167 if (session->internals.priorities.sign_algo.algorithms > 0)
169 ret = _gnutls_sign_algorithm_write_params(session, data, data_size);
170 if (ret < 0)
172 gnutls_assert();
173 return ret;
175 return ret;
179 /* if we are here it means we don't send the extension */
180 return 0;
183 /* Returns a requested by the peer signature algorithm that
184 * matches the given public key algorithm. Index can be increased
185 * to return the second choice etc.
187 gnutls_sign_algorithm_t
188 _gnutls_session_get_sign_algo (gnutls_session_t session,
189 gnutls_pk_algorithm_t pk,
190 gnutls_digest_algorithm_t * hash)
192 unsigned i;
193 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
196 if (!_gnutls_version_has_selectable_sighash (ver) || session->security_parameters.extensions.sign_algorithms_size == 0) /* none set, allow all */
198 *hash = GNUTLS_DIG_SHA1;
199 return _gnutls_x509_pk_to_sign (pk, *hash);
202 for (i = 0;
203 i < session->security_parameters.extensions.sign_algorithms_size; i++)
205 if (_gnutls_sign_get_pk_algorithm
206 (session->security_parameters.extensions.sign_algorithms[i]) == pk)
208 *hash =
209 _gnutls_sign_get_hash_algorithm (session->security_parameters.
210 extensions.sign_algorithms[i]);
211 return session->security_parameters.extensions.sign_algorithms[i];
215 return GNUTLS_SIGN_UNKNOWN;
219 /* Check if the given signature algorithm is accepted by
220 * the peer. Returns 0 on success or a negative value
221 * on error.
224 _gnutls_session_sign_algo_requested (gnutls_session_t session,
225 gnutls_sign_algorithm_t sig)
227 unsigned i;
228 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
230 if (!_gnutls_version_has_selectable_sighash (ver) || session->security_parameters.extensions.sign_algorithms_size == 0) /* none set, allow all */
232 return 0;
235 for (i = 0;
236 i < session->security_parameters.extensions.sign_algorithms_size; i++)
238 if (session->security_parameters.extensions.sign_algorithms[i] == sig)
240 return 0; /* ok */
244 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
247 /* Check if the given signature algorithm is supported.
248 * This means that it is enabled by the priority functions,
249 * and in case of a server a matching certificate exists.
252 _gnutls_session_sign_algo_enabled (gnutls_session_t session,
253 gnutls_sign_algorithm_t sig)
255 unsigned i;
256 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
258 if (!_gnutls_version_has_selectable_sighash (ver) || session->security_parameters.extensions.sign_algorithms_size == 0) /* none set, allow all */
260 return 0;
263 for (i = 0; i < session->internals.priorities.sign_algo.algorithms; i++)
265 if (session->internals.priorities.sign_algo.priority[i] == sig)
267 return 0; /* ok */
271 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
275 * gnutls_session_sign_algorithm_get - Returns the signature algorithms requested by peer
276 * @session: is a #gnutls_session_t structure.
277 * @indx: is an index of the signature algorithm to return
278 * @algo: the returned certificate type will be stored there
280 * Returns the signature algorithm specified by index that was requested
281 * by the peer. If the specified index has no data available
282 * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
283 * If the negotiated TLS version does not support signature algorithms
284 * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
285 * for the first index.
287 * This function is usefull in the certificate callback functions
288 * to assist in selecting the correct certificate.
290 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
291 * an error code is returned.
293 int gnutls_session_sign_algorithm_get_requested (gnutls_session_t session,
294 int indx, gnutls_sign_algorithm_t *algo)
296 gnutls_protocol_t ver = gnutls_protocol_get_version (session);
298 if (!_gnutls_version_has_selectable_sighash (ver) || session->security_parameters.extensions.sign_algorithms_size == 0)
300 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
303 if (indx < session->security_parameters.extensions.sign_algorithms_size)
305 *algo = session->security_parameters.extensions.sign_algorithms[indx];
306 return 0;
308 else
309 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;