]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Allow easier marking of insecure algorithms.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 8 Nov 2012 16:57:01 +0000 (17:57 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 8 Nov 2012 16:57:43 +0000 (17:57 +0100)
NEWS
lib/algorithms.h
lib/algorithms/mac.c
lib/algorithms/sign.c
lib/includes/gnutls/gnutls.h.in
lib/libgnutls.map
lib/verify-tofu.c
lib/x509/ocsp_output.c
lib/x509/output.c
lib/x509/verify.c
tests/chainverify.c

diff --git a/NEWS b/NEWS
index d31de8947beba3f45d9dbd91b36e47dd7ace83ff..20a675a067640654590bf4cdc73ed3334ccdb4c1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -40,6 +40,7 @@ a site's DANE data.
 
 ** API and ABI modifications:
 gnutls_session_get_id2: Added
++gnutls_sign_is_secure: Added
 gnutls_certificate_verify_peers3: Added
 gnutls_ocsp_status_request_is_checked: Added
 gnutls_certificate_verification_status_print: Added
@@ -62,6 +63,7 @@ GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE: Added
 GNUTLS_CERT_UNEXPECTED_OWNER: Added
 GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN: Added
 
+
 * Version 3.1.3 (released 2012-10-12)
 
 ** libgnutls: Added support for the OCSP Certificate Status
index a11a2a2bff5dbfcc0b1bdc6b6f47e96c2c884716..3ee2032aa6b899cc49b5450bbd960b84c22ca384 100644 (file)
@@ -56,6 +56,7 @@ const char *_gnutls_x509_mac_to_oid (gnutls_mac_algorithm_t mac);
 /* Functions for digests. */
 const char *_gnutls_x509_digest_to_oid (gnutls_digest_algorithm_t algorithm);
 const char *_gnutls_digest_get_name (gnutls_digest_algorithm_t algorithm);
+int _gnutls_digest_is_secure (gnutls_digest_algorithm_t algorithm);
 
 /* Functions for cipher suites. */
 int _gnutls_supported_ciphersuites (gnutls_session_t session,
index ad7d57c582ada0d72ae723a7d6a35ddf13d7d032..bcaffb8a05b03e2a8656003aa36495eeeebc5e84 100644 (file)
@@ -32,21 +32,22 @@ struct gnutls_hash_entry
   gnutls_mac_algorithm_t id;
   size_t key_size;              /* in case of mac */
   unsigned placeholder; /* if set, then not a real MAC */
+  unsigned secure; /* if set the this algorithm is secure as hash */
 };
 typedef struct gnutls_hash_entry gnutls_hash_entry;
 
 static const gnutls_hash_entry hash_algorithms[] = {
-  {"SHA1", HASH_OID_SHA1, GNUTLS_MAC_SHA1, 20, 0},
-  {"MD5", HASH_OID_MD5, GNUTLS_MAC_MD5, 16, 0},
-  {"SHA256", HASH_OID_SHA256, GNUTLS_MAC_SHA256, 32, 0},
-  {"SHA384", HASH_OID_SHA384, GNUTLS_MAC_SHA384, 48, 0},
-  {"SHA512", HASH_OID_SHA512, GNUTLS_MAC_SHA512, 64, 0},
-  {"SHA224", HASH_OID_SHA224, GNUTLS_MAC_SHA224, 28, 0},
-  {"AEAD", NULL, GNUTLS_MAC_AEAD, 0, 1},
-  {"MD2", HASH_OID_MD2, GNUTLS_MAC_MD2, 0, 0},     /* not used as MAC */
-  {"RIPEMD160", HASH_OID_RMD160, GNUTLS_MAC_RMD160, 20, 0},
-  {"MAC-NULL", NULL, GNUTLS_MAC_NULL, 0, 0},
-  {0, 0, 0, 0}
+  {"SHA1", HASH_OID_SHA1, GNUTLS_MAC_SHA1, 20, 0, 1},
+  {"MD5", HASH_OID_MD5, GNUTLS_MAC_MD5, 16, 0, 0},
+  {"SHA256", HASH_OID_SHA256, GNUTLS_MAC_SHA256, 32, 0, 1},
+  {"SHA384", HASH_OID_SHA384, GNUTLS_MAC_SHA384, 48, 0, 1},
+  {"SHA512", HASH_OID_SHA512, GNUTLS_MAC_SHA512, 64, 0, 1},
+  {"SHA224", HASH_OID_SHA224, GNUTLS_MAC_SHA224, 28, 0, 1},
+  {"AEAD", NULL, GNUTLS_MAC_AEAD, 0, 1, 1},
+  {"MD2", HASH_OID_MD2, GNUTLS_MAC_MD2, 0, 0, 0},     /* not used as MAC */
+  {"RIPEMD160", HASH_OID_RMD160, GNUTLS_MAC_RMD160, 20, 0, 1},
+  {"MAC-NULL", NULL, GNUTLS_MAC_NULL, 0, 0, 0},
+  {0, 0, 0, 0, 0}
 };
 
 
@@ -219,3 +220,14 @@ _gnutls_mac_is_ok (gnutls_mac_algorithm_t algorithm)
     ret = 1;
   return ret;
 }
+
+int
+_gnutls_digest_is_secure (gnutls_digest_algorithm_t algo)
+{
+  ssize_t ret = 0;
+  gnutls_mac_algorithm_t algorithm = algo;
+
+  GNUTLS_HASH_ALG_LOOP (ret = p->secure);
+  
+  return ret;
+}
index 316392ff846c91de51569351491349cec51772dc..823846664dd2e6b6075bf272d6d09b264dfc8127 100644 (file)
@@ -45,32 +45,32 @@ static const sign_algorithm_st unknown_tls_aid = TLS_SIGN_AID_UNKNOWN;
 
 static const gnutls_sign_entry sign_algorithms[] = {
   {"RSA-SHA1", SIG_RSA_SHA1_OID, GNUTLS_SIGN_RSA_SHA1, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA1, {2, 1}},
+   GNUTLS_DIG_SHA1, {2, 1}},
   {"RSA-SHA224", SIG_RSA_SHA224_OID, GNUTLS_SIGN_RSA_SHA224, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA224, {3, 1}},
+   GNUTLS_DIG_SHA224, {3, 1}},
   {"RSA-SHA256", SIG_RSA_SHA256_OID, GNUTLS_SIGN_RSA_SHA256, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA256, {4, 1}},
+   GNUTLS_DIG_SHA256, {4, 1}},
   {"RSA-SHA384", SIG_RSA_SHA384_OID, GNUTLS_SIGN_RSA_SHA384, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA384, {5, 1}},
+   GNUTLS_DIG_SHA384, {5, 1}},
   {"RSA-SHA512", SIG_RSA_SHA512_OID, GNUTLS_SIGN_RSA_SHA512, GNUTLS_PK_RSA,
-   GNUTLS_MAC_SHA512, {6, 1}},
+   GNUTLS_DIG_SHA512, {6, 1}},
   {"RSA-RMD160", SIG_RSA_RMD160_OID, GNUTLS_SIGN_RSA_RMD160, GNUTLS_PK_RSA,
-   GNUTLS_MAC_RMD160, TLS_SIGN_AID_UNKNOWN},
+   GNUTLS_DIG_RMD160, TLS_SIGN_AID_UNKNOWN},
   {"DSA-SHA1", SIG_DSA_SHA1_OID, GNUTLS_SIGN_DSA_SHA1, GNUTLS_PK_DSA,
-   GNUTLS_MAC_SHA1, {2, 2}},
+   GNUTLS_DIG_SHA1, {2, 2}},
   {"DSA-SHA224", SIG_DSA_SHA224_OID, GNUTLS_SIGN_DSA_SHA224, GNUTLS_PK_DSA,
-   GNUTLS_MAC_SHA224, {3, 2}},
+   GNUTLS_DIG_SHA224, {3, 2}},
   {"DSA-SHA256", SIG_DSA_SHA256_OID, GNUTLS_SIGN_DSA_SHA256, GNUTLS_PK_DSA,
-   GNUTLS_MAC_SHA256, {4, 2}},
+   GNUTLS_DIG_SHA256, {4, 2}},
   {"RSA-MD5", SIG_RSA_MD5_OID, GNUTLS_SIGN_RSA_MD5, GNUTLS_PK_RSA,
-   GNUTLS_MAC_MD5, {1, 1}},
+   GNUTLS_DIG_MD5, {1, 1}},
   {"RSA-MD2", SIG_RSA_MD2_OID, GNUTLS_SIGN_RSA_MD2, GNUTLS_PK_RSA,
-   GNUTLS_MAC_MD2, TLS_SIGN_AID_UNKNOWN},
-  {"ECDSA-SHA1", "1.2.840.10045.4.1", GNUTLS_SIGN_ECDSA_SHA1, GNUTLS_PK_EC, GNUTLS_MAC_SHA1, {2, 3}},
-  {"ECDSA-SHA224", "1.2.840.10045.4.3.1", GNUTLS_SIGN_ECDSA_SHA224, GNUTLS_PK_EC, GNUTLS_MAC_SHA224, {3, 3}},
-  {"ECDSA-SHA256", "1.2.840.10045.4.3.2", GNUTLS_SIGN_ECDSA_SHA256, GNUTLS_PK_EC, GNUTLS_MAC_SHA256, {4, 3}},
-  {"ECDSA-SHA384", "1.2.840.10045.4.3.3", GNUTLS_SIGN_ECDSA_SHA384, GNUTLS_PK_EC, GNUTLS_MAC_SHA384, {5, 3}},
-  {"ECDSA-SHA512", "1.2.840.10045.4.3.4", GNUTLS_SIGN_ECDSA_SHA512, GNUTLS_PK_EC, GNUTLS_MAC_SHA512, {6, 3}},
+   GNUTLS_DIG_MD2, TLS_SIGN_AID_UNKNOWN},
+  {"ECDSA-SHA1", "1.2.840.10045.4.1", GNUTLS_SIGN_ECDSA_SHA1, GNUTLS_PK_EC, GNUTLS_DIG_SHA1, {2, 3}},
+  {"ECDSA-SHA224", "1.2.840.10045.4.3.1", GNUTLS_SIGN_ECDSA_SHA224, GNUTLS_PK_EC, GNUTLS_DIG_SHA224, {3, 3}},
+  {"ECDSA-SHA256", "1.2.840.10045.4.3.2", GNUTLS_SIGN_ECDSA_SHA256, GNUTLS_PK_EC, GNUTLS_DIG_SHA256, {4, 3}},
+  {"ECDSA-SHA384", "1.2.840.10045.4.3.3", GNUTLS_SIGN_ECDSA_SHA384, GNUTLS_PK_EC, GNUTLS_DIG_SHA384, {5, 3}},
+  {"ECDSA-SHA512", "1.2.840.10045.4.3.4", GNUTLS_SIGN_ECDSA_SHA512, GNUTLS_PK_EC, GNUTLS_DIG_SHA512, {6, 3}},
   {"GOST R 34.10-2001", SIG_GOST_R3410_2001_OID, 0, 0, 0,
    TLS_SIGN_AID_UNKNOWN},
   {"GOST R 34.10-94", SIG_GOST_R3410_94_OID, 0, 0, 0, TLS_SIGN_AID_UNKNOWN},
@@ -107,6 +107,27 @@ gnutls_sign_get_name (gnutls_sign_algorithm_t algorithm)
   return ret;
 }
 
+/**
+ * gnutls_sign_is_secure:
+ * @algorithm: is a sign algorithm
+ *
+ * Returns: Non-zero if the provided signature algorithm is considered to be secure.
+ **/
+int 
+gnutls_sign_is_secure (gnutls_sign_algorithm_t algorithm)
+{
+  gnutls_sign_algorithm_t sign = algorithm;
+  gnutls_digest_algorithm_t dig = GNUTLS_DIG_UNKNOWN;
+
+  /* avoid prefix */
+  GNUTLS_SIGN_ALG_LOOP (dig = p->mac);
+  
+  if (dig != GNUTLS_DIG_UNKNOWN)
+    return _gnutls_digest_is_secure(dig);
+
+  return 0;
+}
+
 /**
  * gnutls_sign_list:
  *
index 800323fc7c273fabf16f218d673a7a667d7d911e..0a07565fb2d0d5346e071560e7758f9f05b254e2 100644 (file)
@@ -819,6 +819,8 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
                                                 type);
   const char *gnutls_pk_get_name (gnutls_pk_algorithm_t algorithm);
   const char *gnutls_sign_get_name (gnutls_sign_algorithm_t algorithm);
+  
+  int gnutls_sign_is_secure (gnutls_sign_algorithm_t algorithm);
   gnutls_digest_algorithm_t
   gnutls_sign_get_hash_algorithm (gnutls_sign_algorithm_t sign);
   gnutls_pk_algorithm_t
index 201bdda3e43e02ac6f58c1a5bfee70536ca59974..a8c1c080fcd819dedd1375fb0895eaf50ef16624 100644 (file)
@@ -869,6 +869,7 @@ GNUTLS_3_1_0 {
        gnutls_srtp_get_mki;
        gnutls_srtp_set_mki;
        gnutls_ocsp_status_request_is_checked;
+       gnutls_sign_is_secure;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
index d97d43d7ea2420b928b3b21f3c4d1d6da199ba87..3592395803f1d6e11afa2f31ff8201f9d059ff42 100644 (file)
@@ -700,7 +700,7 @@ FILE* fd = NULL;
 int ret;
 char local_file[MAX_FILENAME];
 
-  if (hash_algo == GNUTLS_DIG_MD5 || hash_algo == GNUTLS_DIG_MD2)
+  if (_gnutls_digest_is_secure(hash_algo) == 0)
     return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
     
   if (_gnutls_hash_get_algo_len(hash_algo) != hash->size)
index 6b60872a148a5b684ddb1a698e1e71080bc9a3ea..853404fd6f9d8e06a32cd4c8c3946c431f20ab37 100644 (file)
@@ -513,7 +513,7 @@ print_resp (gnutls_buffer_st * str, gnutls_ocsp_resp_t resp,
          name = _("unknown");
        addf (str, _("\tSignature Algorithm: %s\n"), name);
       }
-    if (ret == GNUTLS_SIGN_RSA_MD5 || ret == GNUTLS_SIGN_RSA_MD2)
+    if (gnutls_sign_is_secure(ret) == 0)
       {
        adds (str, _("warning: signed using a broken signature "
                     "algorithm that can be forged.\n"));
index c2f0cb42e87a6e1dcbddc6a16c8b4613279eed5b..18db408204e13d70e377f764712a34995ac9fb3f 100644 (file)
@@ -1420,7 +1420,7 @@ print_cert (gnutls_buffer_st * str, gnutls_x509_crt_t cert, int notsigned)
             name = _("unknown");
           addf (str, _("\tSignature Algorithm: %s\n"), name);
         }
-      if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2)
+      if (gnutls_sign_is_secure(err) == 0)
         {
           adds (str, _("warning: signed using a broken signature "
                        "algorithm that can be forged.\n"));
@@ -1608,7 +1608,7 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
         const char *name = gnutls_sign_algorithm_get_name (err);
         if (name == NULL)
           name = _("unknown");
-        if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2)
+        if (gnutls_sign_is_secure(err) == 0)
           addf (str, _("signed using %s (broken!), "), name);
         else
           addf (str, _("signed using %s, "), name);
@@ -2037,7 +2037,7 @@ print_crl (gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
             name = _("unknown");
           addf (str, _("\tSignature Algorithm: %s\n"), name);
         }
-      if (err == GNUTLS_SIGN_RSA_MD5 || err == GNUTLS_SIGN_RSA_MD2)
+      if (gnutls_sign_is_secure(err) == 0)
         {
           adds (str, _("warning: signed using a broken signature "
                        "algorithm that can be forged.\n"));
index 636ae0e27ea8a86eb1100f4adf78f56592c0fe2d..ef36fe52aa83e3c7126a681478c6814070c508f8 100644 (file)
@@ -387,6 +387,16 @@ check_time (gnutls_x509_crt_t crt, time_t now)
   return 0;
 }
 
+static
+int is_broken_allowed( gnutls_sign_algorithm_t sig, unsigned int flags)
+{
+  if ((sig == GNUTLS_SIGN_RSA_MD2) && (flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2))
+    return 1;
+  if ((sig == GNUTLS_SIGN_RSA_MD5) && (flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))
+    return 1;
+  return 0;
+}
+
 /* 
  * Verifies the given certificate again a certificate list of
  * trusted CAs.
@@ -538,10 +548,7 @@ _gnutls_verify_certificate2 (gnutls_x509_crt_t cert,
 
       sigalg = gnutls_x509_crt_get_signature_algorithm (cert);
 
-      if (((sigalg == GNUTLS_SIGN_RSA_MD2) &&
-           !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) ||
-          ((sigalg == GNUTLS_SIGN_RSA_MD5) &&
-           !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5)))
+      if (gnutls_sign_is_secure(sigalg) == 0 && is_broken_allowed(sigalg, flags) == 0)
         {
           out = GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID;
           if (output)
index e099b484083a335259d8bc7d3cd9a9545a668c6a..8e4c21de568c9628ddeba915def0ee23d625fdd5 100644 (file)
@@ -892,8 +892,13 @@ doit (void)
 
       if (verify_status != chains[i].expected_verify_result)
         {
-          fail ("chain[%s]: verify_status: %d expected: %d\n", chains[i].name,
-                verify_status, chains[i].expected_verify_result);
+          gnutls_datum_t out1, out2;
+          gnutls_certificate_verification_status_print(verify_status, GNUTLS_CRT_X509, &out1, 0);
+          gnutls_certificate_verification_status_print(chains[i].expected_verify_result, GNUTLS_CRT_X509, &out2, 0);
+          fail ("chain[%s]:\nverify_status: %d: %s\nexpected: %d: %s\n", chains[i].name,
+                verify_status, out1.data, chains[i].expected_verify_result, out2.data);
+          gnutls_free(out1.data);
+          gnutls_free(out2.data);
 
 #if 0
           j = 0;