diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-06-03 09:55:13 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-06-03 09:55:13 +0200 |
commit | 8020421946266ad6499cadff7a451a39fc36d88e (patch) | |
tree | 24ae5de92e46409a4c7aad1e55d0854d8a642a95 | |
parent | c192c6fbf31ae1db05155a8e1b6029c241303938 (diff) | |
download | gnutls-8020421946266ad6499cadff7a451a39fc36d88e.tar.gz |
Hash algorithms used for DSA and ECDSA correspond to draft-mavrogiannopoulos-tls-dss-00.txt.
-rw-r--r-- | lib/ext/signature.c | 1 | ||||
-rw-r--r-- | lib/gnutls_pubkey.c | 20 | ||||
-rw-r--r-- | lib/nettle/pk.c | 39 | ||||
-rw-r--r-- | lib/x509/common.h | 3 | ||||
-rw-r--r-- | lib/x509/verify.c | 36 |
5 files changed, 58 insertions, 41 deletions
diff --git a/lib/ext/signature.c b/lib/ext/signature.c index d2abd48e5b..9ba7350df8 100644 --- a/lib/ext/signature.c +++ b/lib/ext/signature.c @@ -34,7 +34,6 @@ #include <gnutls_state.h> #include <gnutls_num.h> #include <algorithms.h> -#include <x509/common.h> /* dsa_q_to_hash */ #include <abstract_int.h> static int _gnutls_signature_algorithm_recv_params (gnutls_session_t session, diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index 227036d744..4400e6fe43 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -1197,9 +1197,12 @@ 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) { +int hash_size; +int hash_algo; + if (pubkey->pk_algorithm == GNUTLS_PK_DSA) - { /* override */ - int hash_algo = _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, &pubkey->params); + { + hash_algo = _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, &pubkey->params, &hash_size); /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */ if (!_gnutls_version_has_selectable_sighash (ver)) @@ -1209,7 +1212,18 @@ int _gnutls_pubkey_compatible_with_sig(gnutls_pubkey_t pubkey, gnutls_protocol_t } else if (sign != GNUTLS_SIGN_UNKNOWN) { - if (_gnutls_sign_get_hash_algorithm(sign) != hash_algo) + if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) != hash_size) + return GNUTLS_E_UNWANTED_ALGORITHM; + } + + } + else if (pubkey->pk_algorithm == GNUTLS_PK_ECC) + { + hash_algo = _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, &pubkey->params, &hash_size); + + if (_gnutls_version_has_selectable_sighash (ver) && sign != GNUTLS_SIGN_UNKNOWN) + { + if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) != hash_size) return GNUTLS_E_UNWANTED_ALGORITHM; } diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index 15696cd681..b286027c09 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -359,15 +359,14 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo, dsa_signature_init (&sig); - hash = _gnutls_dsa_q_to_hash (algo, pk_params); - hash_len = _gnutls_hash_get_algo_len (hash); + hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) { gnutls_assert (); _gnutls_debug_log("Security level of algorithm requires hash %s or better\n", gnutls_mac_get_name(hash)); } - ret = ecc_sign_hash(vdata->data, vdata->size, + ret = ecc_sign_hash(vdata->data, hash_len, &sig, NULL, rnd_func, &priv); if (ret != 0) { @@ -402,8 +401,7 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo, dsa_signature_init (&sig); - hash = _gnutls_dsa_q_to_hash (algo, pk_params); - hash_len = _gnutls_hash_get_algo_len (hash); + hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) { gnutls_assert (); @@ -533,7 +531,7 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo, { ecc_key pub; struct dsa_signature sig; - int stat; + int stat, hash_len; ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) @@ -546,19 +544,15 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo, memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); - hash = _gnutls_dsa_q_to_hash (algo, pk_params); - if (vdata->size != _gnutls_hash_get_algo_len (hash)) + hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); + if (vdata->size < hash_len) { gnutls_assert (); - - if (vdata->size < 20) - { - ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; - goto ecdsa_fail; - } + ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; + goto ecdsa_fail; } - ret = ecc_verify_hash(&sig, vdata->data, vdata->size, &stat, &pub); + ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub); if (ret != 0 || stat != 1) { gnutls_assert(); @@ -576,6 +570,7 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo, { struct dsa_public_key pub; struct dsa_signature sig; + int hash_len; ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) @@ -588,19 +583,15 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo, memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); - hash = _gnutls_dsa_q_to_hash (algo, pk_params); - if (vdata->size != _gnutls_hash_get_algo_len (hash)) + hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); + if (vdata->size < hash_len) { gnutls_assert (); - - if (vdata->size < 20) - { - ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; - goto dsa_fail; - } + ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; + goto dsa_fail; } - ret = _dsa_verify (&pub, vdata->size, vdata->data, &sig); + ret = _dsa_verify (&pub, hash_len, vdata->data, &sig); if (ret == 0) { gnutls_assert(); diff --git a/lib/x509/common.h b/lib/x509/common.h index b0251621dd..0e96337e72 100644 --- a/lib/x509/common.h +++ b/lib/x509/common.h @@ -140,7 +140,8 @@ int _gnutls_x509_get_signed_data (ASN1_TYPE src, const char *src_name, int _gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name, gnutls_datum_t * signature); -gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params); +gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, + const gnutls_pk_params_st* params, int* hash_len); int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root, gnutls_pk_params_st * params); diff --git a/lib/x509/verify.c b/lib/x509/verify.c index 1170c048c8..df45746db3 100644 --- a/lib/x509/verify.c +++ b/lib/x509/verify.c @@ -827,7 +827,7 @@ _pkcs1_rsa_verify_sig (const gnutls_datum_t * text, /* Hashes input data and verifies a signature. */ static int -verify_sig (const gnutls_datum_t * text, +dsa_verify_sig (const gnutls_datum_t * text, const gnutls_datum_t * hash, const gnutls_datum_t * signature, gnutls_pk_algorithm_t pk, @@ -838,18 +838,17 @@ verify_sig (const gnutls_datum_t * text, gnutls_datum_t digest; digest_hd_st hd; gnutls_digest_algorithm_t algo; + int hash_len; - algo = _gnutls_dsa_q_to_hash (pk, params); + algo = _gnutls_dsa_q_to_hash (pk, params, &hash_len); if (hash) { /* SHA1 or better allowed */ - if (!hash->data || hash->size != _gnutls_hash_get_algo_len(algo)) + if (!hash->data || hash->size < hash_len) { gnutls_assert(); - _gnutls_debug_log("Hash size (%d) does not correspond to hash %s.\n", (int)hash->size, gnutls_mac_get_name(algo)); - - if (hash->size < 20) - return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); + _gnutls_debug_log("Hash size (%d) does not correspond to hash %s or better.\n", (int)hash->size, gnutls_mac_get_name(algo)); + return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); } digest = *hash; @@ -902,7 +901,7 @@ pubkey_verify_sig (const gnutls_datum_t * tbs, case GNUTLS_PK_ECC: case GNUTLS_PK_DSA: - if (verify_sig(tbs, hash, signature, pk, issuer_params) != 0) + if (dsa_verify_sig(tbs, hash, signature, pk, issuer_params) != 0) { gnutls_assert (); return GNUTLS_E_PK_SIG_VERIFY_FAILED; @@ -918,7 +917,7 @@ pubkey_verify_sig (const gnutls_datum_t * tbs, } gnutls_digest_algorithm_t -_gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params) +_gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params, int* hash_len) { int bits = 0; @@ -929,16 +928,29 @@ _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* pa if (bits <= 160) { + if (hash_len) *hash_len = 20; return GNUTLS_DIG_SHA1; } else if (bits <= 224) { - return GNUTLS_DIG_SHA224; + if (hash_len) *hash_len = 28; + return GNUTLS_DIG_SHA256; } - else + else if (bits <= 256) { + if (hash_len) *hash_len = 32; return GNUTLS_DIG_SHA256; } + else if (bits <= 384) + { + if (hash_len) *hash_len = 48; + return GNUTLS_DIG_SHA384; + } + else + { + if (hash_len) *hash_len = 64; + return GNUTLS_DIG_SHA512; + } } /* This will return the appropriate hash to verify the given signature. @@ -962,7 +974,7 @@ _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash, case GNUTLS_PK_ECC: if (hash) - *hash = _gnutls_dsa_q_to_hash (pk, issuer_params); + *hash = _gnutls_dsa_q_to_hash (pk, issuer_params, NULL); ret = 0; break; |