diff options
Diffstat (limited to 'lib/ext_signature.c')
-rw-r--r-- | lib/ext_signature.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/lib/ext_signature.c b/lib/ext_signature.c index 5e62f5c599..edfb386cf1 100644 --- a/lib/ext_signature.c +++ b/lib/ext_signature.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002, 2003, 2004, 2005, 2009, 2010 Free Software + * Copyright (C) 2002,2003,2004,2005,2009,2010,2011 Free Software * Foundation, Inc. * * Author: Nikos Mavrogiannopoulos @@ -34,6 +34,8 @@ #include <gnutls_state.h> #include <gnutls_num.h> #include <gnutls_algorithms.h> +#include <x509/common.h> /* dsa_q_to_hash */ +#include <gnutls_cert.h> static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session, const opaque * data, @@ -244,13 +246,36 @@ _gnutls_signature_algorithm_send_params (gnutls_session_t session, return 0; } +int cert_compatible_with_sig(gnutls_cert* cert, gnutls_protocol_t ver, + gnutls_sign_algorithm_t sign) +{ + if (cert->subject_pk_algorithm == GNUTLS_PK_DSA) + { /* override */ + int hash_algo = _gnutls_dsa_q_to_hash (cert->params[1]); + + /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */ + if (!_gnutls_version_has_selectable_sighash (ver)) + { + if (hash_algo != GNUTLS_DIG_SHA1) + return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL); + } + else + { + if (_gnutls_sign_get_hash_algorithm(sign) != hash_algo) + return GNUTLS_E_UNWANTED_ALGORITHM; + } + + } + + return 0; +} + /* Returns a requested by the peer signature algorithm that * matches the given public key algorithm. Index can be increased * to return the second choice etc. */ gnutls_sign_algorithm_t -_gnutls_session_get_sign_algo (gnutls_session_t session, - gnutls_pk_algorithm_t pk) +_gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_cert* cert) { unsigned i; int ret; @@ -266,15 +291,18 @@ _gnutls_session_get_sign_algo (gnutls_session_t session, if (ret < 0 || !_gnutls_version_has_selectable_sighash (ver) || priv->sign_algorithms_size == 0) - /* none set, allow all */ + /* none set, allow SHA-1 only */ { - return _gnutls_x509_pk_to_sign (pk, GNUTLS_DIG_SHA1); + return _gnutls_x509_pk_to_sign (cert->subject_pk_algorithm, GNUTLS_DIG_SHA1); } for (i = 0; i < priv->sign_algorithms_size; i++) { - if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == pk) + if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == cert->subject_pk_algorithm) { + if (cert_compatible_with_sig(cert, ver, priv->sign_algorithms[i]) < 0) + continue; + return priv->sign_algorithms[i]; } } |