]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Re-enable the certificate key usage checks for compliance with ciphersuite
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 14 Aug 2015 09:27:50 +0000 (11:27 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 14 Aug 2015 09:27:50 +0000 (11:27 +0200)
There is a new attack on the TLS protocol which relies on using certificates
for ECDSA as certificates for ECDH ciphersuites. That attack while it doesn't
affect gnutls, which doesn't support static ECDH, assumes that implementations
ignore the key usage bits in the certificate. We have done it since 3.1.0 for
compatibility reasons (see http://www.gnutls.org/faq.html#key-usage-violation),
but that clearly opens the door for real attacks in the future.

For this reason the key usage bits will no longer be ignored.

Resolves #24

lib/gnutls_int.h
lib/gnutls_sig.c

index a8bc811cccfc3f5c7a51d22ad998f307c17caba1..3f327943e06b3d86088ba13ffcf093ec915d39e2 100644 (file)
@@ -662,6 +662,7 @@ struct gnutls_priority_st {
        safe_renegotiation_t sr;
        bool min_record_version;
        bool server_precedence;
+       bool allow_key_usage_violation;
        bool allow_wrong_pms;
        bool no_tickets;
        bool no_etm;
@@ -690,6 +691,7 @@ struct gnutls_priority_st {
               (x)->allow_large_records = 1; \
               (x)->no_etm = 1; \
               (x)->no_ext_master_secret = 1; \
+              (x)->allow_key_usage_violation = 1; \
               (x)->allow_wrong_pms = 1; \
               (x)->dumbfw = 1
 
index 4764e14ab493f02a00460a4ffc428c318a7f4170..215404b1701c70c0804b9ccb8bbb7de061742148 100644 (file)
@@ -157,6 +157,25 @@ _gnutls_handshake_sign_data(gnutls_session_t session,
 
 }
 
+static
+int check_key_usage_for_sig(gnutls_session_t session, unsigned key_usage)
+{
+       if (key_usage != 0) {
+               if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
+                       gnutls_assert();
+                       if (session->internals.priorities.allow_key_usage_violation == 0) {
+                               _gnutls_audit_log(session,
+                                         "Peer's certificate does not allow digital signatures. Key usage violation detected.\n");
+                               return GNUTLS_E_KEY_USAGE_VIOLATION;
+                       } else {
+                               _gnutls_audit_log(session,
+                                         "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n");
+                       }
+               }
+       }
+       return 0;
+}
+
 /* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
  * Cert is the certificate of the corresponding private key. It is only checked if
  * it supports signing.
@@ -169,19 +188,16 @@ sign_tls_hash(gnutls_session_t session, const mac_entry_st * hash_algo,
 {
        const version_entry_st *ver = get_version(session);
        unsigned int key_usage = 0;
+       int ret;
 
        /* If our certificate supports signing
         */
        if (cert != NULL) {
                gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
 
-               if (key_usage != 0) {
-                       if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
-                               gnutls_assert();
-                               _gnutls_audit_log(session,
-                                                 "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n");
-                       }
-               }
+               ret = check_key_usage_for_sig(session, key_usage);
+               if (ret < 0)
+                       return gnutls_assert_val(ret);
        }
 
        if (!_gnutls_version_has_selectable_sighash(ver))
@@ -212,14 +228,9 @@ verify_tls_hash(gnutls_session_t session,
 
        gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);
 
-       /* If the certificate supports signing continue.
-        */
-       if (key_usage != 0)
-               if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
-                       gnutls_assert();
-                       _gnutls_audit_log(session,
-                                         "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n");
-               }
+       ret = check_key_usage_for_sig(session, key_usage);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
 
        if (pk_algo == GNUTLS_PK_UNKNOWN)
                pk_algo =