summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-06-03 09:55:13 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-06-03 09:55:13 +0200
commit8020421946266ad6499cadff7a451a39fc36d88e (patch)
tree24ae5de92e46409a4c7aad1e55d0854d8a642a95
parentc192c6fbf31ae1db05155a8e1b6029c241303938 (diff)
downloadgnutls-8020421946266ad6499cadff7a451a39fc36d88e.tar.gz
Hash algorithms used for DSA and ECDSA correspond to draft-mavrogiannopoulos-tls-dss-00.txt.
-rw-r--r--lib/ext/signature.c1
-rw-r--r--lib/gnutls_pubkey.c20
-rw-r--r--lib/nettle/pk.c39
-rw-r--r--lib/x509/common.h3
-rw-r--r--lib/x509/verify.c36
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;