diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-06-04 22:13:51 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-06-04 22:14:25 +0200 |
commit | 0f6e058baca642acbdcbb23f055f4b4dd71d402b (patch) | |
tree | f987300c2e94305a9d82b979fe0a48e7ab927014 | |
parent | 0b34266779b5600e3985fdbd7a0a473bc549318f (diff) | |
download | gnutls-0f6e058baca642acbdcbb23f055f4b4dd71d402b.tar.gz |
Follow http://tools.ietf.org/html/draft-mavrogiannopoulos-tls-dss-00 in DSA signature generation.
-rw-r--r-- | lib/ext_signature.c | 6 | ||||
-rw-r--r-- | lib/gnutls_sig.c | 18 | ||||
-rw-r--r-- | lib/nettle/pk.c | 21 | ||||
-rw-r--r-- | lib/x509/common.h | 2 | ||||
-rw-r--r-- | lib/x509/verify.c | 18 |
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; |