summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-06-04 22:13:51 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-06-04 22:14:25 +0200
commit0f6e058baca642acbdcbb23f055f4b4dd71d402b (patch)
treef987300c2e94305a9d82b979fe0a48e7ab927014
parent0b34266779b5600e3985fdbd7a0a473bc549318f (diff)
downloadgnutls-0f6e058baca642acbdcbb23f055f4b4dd71d402b.tar.gz
Follow http://tools.ietf.org/html/draft-mavrogiannopoulos-tls-dss-00 in DSA signature generation.
-rw-r--r--lib/ext_signature.c6
-rw-r--r--lib/gnutls_sig.c18
-rw-r--r--lib/nettle/pk.c21
-rw-r--r--lib/x509/common.h2
-rw-r--r--lib/x509/verify.c18
5 files changed, 28 insertions, 37 deletions
diff --git a/lib/ext_signature.c b/lib/ext_signature.c
index edfb386cf1..48eb5358e3 100644
--- a/lib/ext_signature.c
+++ b/lib/ext_signature.c
@@ -249,9 +249,11 @@ _gnutls_signature_algorithm_send_params (gnutls_session_t session,
int cert_compatible_with_sig(gnutls_cert* cert, gnutls_protocol_t ver,
gnutls_sign_algorithm_t sign)
{
+unsigned int hash_len;
+
if (cert->subject_pk_algorithm == GNUTLS_PK_DSA)
{ /* override */
- int hash_algo = _gnutls_dsa_q_to_hash (cert->params[1]);
+ int hash_algo = _gnutls_dsa_q_to_hash (cert->params[1], &hash_len);
/* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
if (!_gnutls_version_has_selectable_sighash (ver))
@@ -261,7 +263,7 @@ int cert_compatible_with_sig(gnutls_cert* cert, gnutls_protocol_t ver,
}
else
{
- if (_gnutls_sign_get_hash_algorithm(sign) != hash_algo)
+ if (_gnutls_hash_get_algo_len(_gnutls_sign_get_hash_algorithm(sign)) < hash_len)
return GNUTLS_E_UNWANTED_ALGORITHM;
}
diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c
index 82155f467b..9a925c3eba 100644
--- a/lib/gnutls_sig.c
+++ b/lib/gnutls_sig.c
@@ -711,7 +711,7 @@ _gnutls_handshake_sign_cert_vrfy (gnutls_session_t session,
break;
case GNUTLS_PK_DSA:
/* ensure 1024 bit DSA keys are used */
- hash_algo = _gnutls_dsa_q_to_hash (cert->params[1]);
+ hash_algo = _gnutls_dsa_q_to_hash (cert->params[1], NULL);
if (!_gnutls_version_has_selectable_sighash (ver) && hash_algo != GNUTLS_DIG_SHA1)
return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
@@ -738,22 +738,6 @@ pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
{
int ret;
- switch (pk)
- {
- case GNUTLS_PK_RSA:
- break;
- case GNUTLS_PK_DSA:
- if (params && hash != _gnutls_dsa_q_to_hash (params[1]))
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
- break;
- default:
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
digest->size = _gnutls_hash_get_algo_len (hash);
digest->data = gnutls_malloc (digest->size);
if (digest->data == NULL)
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 9af3739e68..505c6b4048 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -276,7 +276,7 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
struct dsa_public_key pub;
struct dsa_private_key priv;
struct dsa_signature sig;
- int hash_len;
+ unsigned int hash_len;
memset(&priv, 0, sizeof(priv));
memset(&pub, 0, sizeof(pub));
@@ -285,13 +285,12 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
dsa_signature_init (&sig);
- hash = _gnutls_dsa_q_to_hash (pub.q);
- hash_len = _gnutls_hash_get_algo_len (hash);
+ hash = _gnutls_dsa_q_to_hash (pub.q, &hash_len);
if (hash_len > vdata->size)
{
gnutls_assert ();
- ret = GNUTLS_E_PK_SIGN_FAILED;
- goto dsa_fail;
+ _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
+ hash_len = vdata->size;
}
ret =
@@ -417,6 +416,7 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
{
struct dsa_public_key pub;
struct dsa_signature sig;
+ unsigned int hash_len;
ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
if (ret < 0)
@@ -429,16 +429,16 @@ _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 (pub.q);
+ hash = _gnutls_dsa_q_to_hash (pub.q, &hash_len);
- if (vdata->size != _gnutls_hash_get_algo_len (hash))
+ if (hash_len > vdata->size)
{
gnutls_assert ();
- ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
- goto dsa_fail;
+ _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
+ hash_len = vdata->size;
}
- ret = _dsa_verify (&pub, vdata->size, vdata->data, &sig);
+ ret = _dsa_verify (&pub, hash_len, vdata->data, &sig);
if (ret == 0)
{
gnutls_assert();
@@ -447,7 +447,6 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
else
ret = 0;
- dsa_fail:
_gnutls_mpi_release (&tmp[0]);
_gnutls_mpi_release (&tmp[1]);
break;
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 05526fd83a..5cc6a109c6 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -139,7 +139,7 @@ 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 (bigint_t q);
+gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (bigint_t q, unsigned int* hash_len);
int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
bigint_t * params, int *params_size);
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index 86f7f76b32..97606bead5 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -798,16 +798,19 @@ dsa_verify_sig (const gnutls_datum_t * text,
gnutls_datum_t digest;
digest_hd_st hd;
gnutls_digest_algorithm_t algo;
+ unsigned int hash_len;
- algo = _gnutls_dsa_q_to_hash (params[1]);
+ algo = _gnutls_dsa_q_to_hash (params[1], &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", (int)hash->size, gnutls_mac_get_name(algo));
- return GNUTLS_E_INVALID_REQUEST;
+
+ if (hash->size != 20)
+ return GNUTLS_E_PK_SIG_VERIFY_FAILED;
}
digest = *hash;
}
@@ -876,20 +879,23 @@ pubkey_verify_sig (const gnutls_datum_t * tbs,
}
gnutls_digest_algorithm_t
-_gnutls_dsa_q_to_hash (bigint_t q)
+_gnutls_dsa_q_to_hash (bigint_t q, unsigned int* hash_len)
{
int bits = _gnutls_mpi_get_nbits (q);
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
{
+ if (hash_len) *hash_len = 32;
return GNUTLS_DIG_SHA256;
}
}
@@ -915,7 +921,7 @@ _gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash,
case GNUTLS_PK_DSA:
if (hash)
- *hash = _gnutls_dsa_q_to_hash (issuer_params[1]);
+ *hash = _gnutls_dsa_q_to_hash (issuer_params[1], NULL);
ret = 0;
break;