From 5bd518deaab699d46164f9e82744f482f3dabde7 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 1 Sep 2012 19:07:18 +0200 Subject: [PATCH] Be tolerant in ECDSA-violating signatures. --- NEWS | 4 ++++ lib/abstract_int.h | 4 ++-- lib/ext/signature.c | 2 +- lib/gnutls_pubkey.c | 22 +++++++++++++++------- lib/gnutls_sig.c | 4 ++-- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index bb6d8e6bc..a97197281 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ See the end for copying conditions. ** gnutls-serv: Listens on IPv6. Patch by Bernhard R. Link. +** libgnutls: Be tolerant in ECDSA signature violations (e.g. using +SHA256 with a SECP384 curve instead of SHA-384), to interoperate with +openssl. + ** libgnutls: Fixed DSA and ECDSA signature generation in smart cards. diff --git a/lib/abstract_int.h b/lib/abstract_int.h index 429d27e50..7a42b09db 100644 --- a/lib/abstract_int.h +++ b/lib/abstract_int.h @@ -29,8 +29,8 @@ int _gnutls_privkey_get_public_mpis (gnutls_privkey_t key, gnutls_pk_params_st*); int pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st* params); -int _gnutls_pubkey_compatible_with_sig(gnutls_pubkey_t pubkey, gnutls_protocol_t ver, - gnutls_sign_algorithm_t sign); +int _gnutls_pubkey_compatible_with_sig(gnutls_session_t, gnutls_pubkey_t pubkey, + gnutls_protocol_t ver, gnutls_sign_algorithm_t sign); int _gnutls_pubkey_is_over_rsa_512(gnutls_pubkey_t pubkey); int _gnutls_pubkey_get_mpis (gnutls_pubkey_t key, diff --git a/lib/ext/signature.c b/lib/ext/signature.c index d52091ad2..46dc5a687 100644 --- a/lib/ext/signature.c +++ b/lib/ext/signature.c @@ -271,7 +271,7 @@ _gnutls_session_get_sign_algo (gnutls_session_t session, gnutls_pcert_st* cert) { if (_gnutls_sign_get_pk_algorithm (priv->sign_algorithms[i]) == cert_algo) { - if (_gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, priv->sign_algorithms[i]) < 0) + if (_gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, priv->sign_algorithms[i]) < 0) continue; if (_gnutls_session_sign_algo_enabled(session, priv->sign_algorithms[i]) < 0) diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index 39246f774..f2be13031 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -1506,12 +1506,18 @@ gnutls_pubkey_get_verify_algorithm (gnutls_pubkey_t key, } - -int _gnutls_pubkey_compatible_with_sig(gnutls_pubkey_t pubkey, gnutls_protocol_t ver, - gnutls_sign_algorithm_t sign) +/* Checks whether the public key given is compatible with the + * signature algorithm used. The session is only used for audit logging, and + * it may be null. + */ +int _gnutls_pubkey_compatible_with_sig(gnutls_session_t session, + gnutls_pubkey_t pubkey, + gnutls_protocol_t ver, + gnutls_sign_algorithm_t sign) { unsigned int hash_size; unsigned int hash_algo; +unsigned int sig_hash_size; if (pubkey->pk_algorithm == GNUTLS_PK_DSA) { @@ -1525,8 +1531,9 @@ unsigned int hash_algo; } else if (sign != GNUTLS_SIGN_UNKNOWN) { - if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) < hash_size) - return GNUTLS_E_UNWANTED_ALGORITHM; + sig_hash_size = _gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)); + if (sig_hash_size < hash_size) + _gnutls_audit_log(session, "The hash size used in signature (%u) is less than the expected (%u)\n", sig_hash_size, hash_size); } } @@ -1535,9 +1542,10 @@ unsigned int hash_algo; if (_gnutls_version_has_selectable_sighash (ver) && sign != GNUTLS_SIGN_UNKNOWN) { hash_algo = _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, &pubkey->params, &hash_size); + sig_hash_size = _gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)); - if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) < hash_size) - return GNUTLS_E_UNWANTED_ALGORITHM; + if (sig_hash_size < hash_size) + _gnutls_audit_log(session, "The hash size used in signature (%u) is less than the expected (%u)\n", sig_hash_size, hash_size); } } diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index b30dcc330..5a78e026d 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -360,7 +360,7 @@ _gnutls_handshake_verify_data (gnutls_session_t session, gnutls_pcert_st* cert, _gnutls_handshake_log ("HSK[%p]: verify handshake data: using %s\n", session, gnutls_sign_algorithm_get_name (sign_algo)); - ret = _gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, sign_algo); + ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, sign_algo); if (ret < 0) return gnutls_assert_val(ret); @@ -677,7 +677,7 @@ _gnutls_handshake_sign_crt_vrfy (gnutls_session_t session, _gnutls_hash_deinit (&td_sha, &concat[16]); /* ensure 1024 bit DSA keys are used */ - ret = _gnutls_pubkey_compatible_with_sig(cert->pubkey, ver, GNUTLS_SIGN_UNKNOWN); + ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, GNUTLS_SIGN_UNKNOWN); if (ret < 0) return gnutls_assert_val(ret); -- 2.11.4.GIT