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
));
153 if (sig
!= GNUTLS_SIGN_UNKNOWN
)
155 priv
->sign_algorithms
[priv
->sign_algorithms_size
++] = sig
;
156 if (priv
->sign_algorithms_size
== MAX_SIGNATURE_ALGORITHMS
)
162 _gnutls_ext_set_session_data (session
,
163 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS
, epriv
);
169 * In case of a server: if a SIGNATURE_ALGORITHMS extension type is
170 * received then it stores into the session security parameters the
173 * In case of a client: If a signature_algorithms have been specified
174 * then it is an error;
178 _gnutls_signature_algorithm_recv_params (gnutls_session_t session
,
182 ssize_t data_size
= _data_size
;
185 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
187 /* nothing for now */
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; */
197 /* SERVER SIDE - we must check if the sent cert type is the right one
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
);
219 /* returns data_size or a negative number on failure
222 _gnutls_signature_algorithm_send_params (gnutls_session_t session
,
223 opaque
* data
, size_t data_size
)
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)
235 _gnutls_sign_algorithm_write_params (session
, data
, data_size
);
245 /* if we are here it means we don't send the extension */
249 int cert_compatible_with_sig(gnutls_cert
* cert
, gnutls_protocol_t ver
,
250 gnutls_sign_algorithm_t sign
)
252 if (cert
->subject_pk_algorithm
== GNUTLS_PK_DSA
)
254 int hash_algo
= _gnutls_dsa_q_to_hash (cert
->params
[1]);
256 /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
257 if (!_gnutls_version_has_selectable_sighash (ver
))
259 if (hash_algo
!= GNUTLS_DIG_SHA1
)
260 return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL
);
264 if (_gnutls_sign_get_hash_algorithm(sign
) != hash_algo
)
265 return GNUTLS_E_UNWANTED_ALGORITHM
;
273 /* Returns a requested by the peer signature algorithm that
274 * matches the given public key algorithm. Index can be increased
275 * to return the second choice etc.
277 gnutls_sign_algorithm_t
278 _gnutls_session_get_sign_algo (gnutls_session_t session
, gnutls_cert
* cert
)
282 gnutls_protocol_t ver
= gnutls_protocol_get_version (session
);
284 extension_priv_data_t epriv
;
287 _gnutls_ext_get_session_data (session
,
288 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS
,
292 if (ret
< 0 || !_gnutls_version_has_selectable_sighash (ver
)
293 || priv
->sign_algorithms_size
== 0)
294 /* none set, allow SHA-1 only */
296 return _gnutls_x509_pk_to_sign (cert
->subject_pk_algorithm
, GNUTLS_DIG_SHA1
);
299 for (i
= 0; i
< priv
->sign_algorithms_size
; i
++)
301 if (_gnutls_sign_get_pk_algorithm (priv
->sign_algorithms
[i
]) == cert
->subject_pk_algorithm
)
303 if (cert_compatible_with_sig(cert
, ver
, priv
->sign_algorithms
[i
]) < 0)
306 return priv
->sign_algorithms
[i
];
310 return GNUTLS_SIGN_UNKNOWN
;
314 /* Check if the given signature algorithm is accepted by
315 * the peer. Returns 0 on success or a negative value
319 _gnutls_session_sign_algo_requested (gnutls_session_t session
,
320 gnutls_sign_algorithm_t sig
)
324 gnutls_protocol_t ver
= gnutls_protocol_get_version (session
);
326 extension_priv_data_t epriv
;
328 if (!_gnutls_version_has_selectable_sighash (ver
))
334 _gnutls_ext_get_session_data (session
,
335 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS
,
340 /* extension not received allow SHA1 and SHA256 */
341 hash
= _gnutls_sign_get_hash_algorithm (sig
);
342 if (hash
== GNUTLS_DIG_SHA1
|| hash
== GNUTLS_DIG_SHA256
)
349 if (priv
->sign_algorithms_size
== 0)
350 /* none set, allow all */
355 for (i
= 0; i
< priv
->sign_algorithms_size
; i
++)
357 if (priv
->sign_algorithms
[i
] == sig
)
363 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM
;
366 /* Check if the given signature algorithm is supported.
367 * This means that it is enabled by the priority functions,
368 * and in case of a server a matching certificate exists.
371 _gnutls_session_sign_algo_enabled (gnutls_session_t session
,
372 gnutls_sign_algorithm_t sig
)
376 gnutls_protocol_t ver
= gnutls_protocol_get_version (session
);
378 extension_priv_data_t epriv
;
381 _gnutls_ext_get_session_data (session
,
382 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS
,
391 if (!_gnutls_version_has_selectable_sighash (ver
)
392 || priv
->sign_algorithms_size
== 0)
393 /* none set, allow all */
398 for (i
= 0; i
< session
->internals
.priorities
.sign_algo
.algorithms
; i
++)
400 if (session
->internals
.priorities
.sign_algo
.priority
[i
] == sig
)
406 return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM
;
410 signature_algorithms_deinit_data (extension_priv_data_t priv
)
412 gnutls_free (priv
.ptr
);
416 signature_algorithms_pack (extension_priv_data_t epriv
, gnutls_buffer_st
* ps
)
418 sig_ext_st
*priv
= epriv
.ptr
;
421 BUFFER_APPEND_NUM (ps
, priv
->sign_algorithms_size
);
422 for (i
= 0; i
< priv
->sign_algorithms_size
; i
++)
424 BUFFER_APPEND_NUM (ps
, priv
->sign_algorithms
[i
]);
430 signature_algorithms_unpack (gnutls_buffer_st
* ps
,
431 extension_priv_data_t
* _priv
)
435 extension_priv_data_t epriv
;
437 priv
= gnutls_calloc (1, sizeof (*priv
));
441 return GNUTLS_E_MEMORY_ERROR
;
444 BUFFER_POP_NUM (ps
, priv
->sign_algorithms_size
);
445 for (i
= 0; i
< priv
->sign_algorithms_size
; i
++)
447 BUFFER_POP_NUM (ps
, priv
->sign_algorithms
[i
]);
463 * gnutls_sign_algorithm_get_requested:
464 * @session: is a #gnutls_session_t structure.
465 * @indx: is an index of the signature algorithm to return
466 * @algo: the returned certificate type will be stored there
468 * Returns the signature algorithm specified by index that was
469 * requested by the peer. If the specified index has no data available
470 * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If
471 * the negotiated TLS version does not support signature algorithms
472 * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
473 * for the first index. The first index is 0.
475 * This function is useful in the certificate callback functions
476 * to assist in selecting the correct certificate.
478 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
479 * an error code is returned.
484 gnutls_sign_algorithm_get_requested (gnutls_session_t session
,
486 gnutls_sign_algorithm_t
* algo
)
488 gnutls_protocol_t ver
= gnutls_protocol_get_version (session
);
490 extension_priv_data_t epriv
;
494 _gnutls_ext_get_session_data (session
,
495 GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS
,
504 if (!_gnutls_version_has_selectable_sighash (ver
)
505 || priv
->sign_algorithms_size
== 0)
507 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
510 if (indx
< priv
->sign_algorithms_size
)
512 *algo
= priv
->sign_algorithms
[indx
];
516 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;