Bug#737921: [TLS1.2] gnutls only likes SHA1 and SHA256 certificates

Jan Nordholz jnordholz at sec.t-labs.tu-berlin.de
Thu Feb 6 23:14:38 UTC 2014


Package: gnutls26
Version: 2.12.23-10
Severity: minor

Dear GnuTLS maintainers,

I've just spent several hours debugging a problem which I think should be
stated somewhere. (Severity minor as it's a documentation issue.)

After replacing some expired certificates, I wondered why satellite exim4
instances would no longer talk to the one that had just received a new
certificate. With s_client and gnutls-cli-debug I could narrow the problem
down to a problem with TLS1.2 - albeit the reason was completely opaque.
The only output on the server side was the infamous

] (gnutls_handshake): Could not negotiate a supported cipher suite.

After single-stepping through exim and hotpatching _gnutls_log_level and
_gnutls_log_func to meaningful values I found that the library was
removing all the ciphers, accompanied by another, even more cryptic
message about the server certificate:

] Feb  6 23:19:58 $HOST exim4: ASSERT: gnutls_handshake.c:3348
] Feb  6 23:19:58 $HOST exim4: Could not find an appropriate certificate: Insufficient credentials for that request.
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_DSS_ARCFOUR_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_DSS_3DES_EDE_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_DSS_AES_128_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_DSS_AES_256_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_DSS_CAMELLIA_128_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_DSS_CAMELLIA_256_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_DSS_AES_128_CBC_SHA256
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_DSS_AES_256_CBC_SHA256
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_RSA_3DES_EDE_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_RSA_AES_128_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_RSA_AES_256_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_RSA_CAMELLIA_128_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_RSA_CAMELLIA_256_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_RSA_AES_128_CBC_SHA256
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: DHE_RSA_AES_256_CBC_SHA256
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_ARCFOUR_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_ARCFOUR_MD5
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_3DES_EDE_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_AES_128_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_AES_256_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_CAMELLIA_128_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_CAMELLIA_256_CBC_SHA1
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_AES_128_CBC_SHA256
] Feb  6 23:19:58 $HOST exim4: HSK[0x7fe9524e2680]: Removing ciphersuite: RSA_AES_256_CBC_SHA256
] Feb  6 23:19:58 $HOST exim4: ASSERT: gnutls_handshake.c:921
] Feb  6 23:19:58 $HOST exim4: ASSERT: gnutls_handshake.c:586
] Feb  6 23:19:58 $HOST exim4: ASSERT: gnutls_handshake.c:2358
] Feb  6 23:19:58 $HOST exim4: ASSERT: gnutls_handshake.c:2991

$SEARCHING revealed that I might have set improper keyUsage extensions on the
certificate - however there were none, and as I generated another certificate
with explicit keyUsage just to check, sure enough the problem persisted.

So another round of digging into GnuTLS source code, until I finally
stumbled across this gem:

] int
] _gnutls_server_select_cert (gnutls_session_t session,
]                             gnutls_pk_algorithm_t requested_algo)
] {
] [...]
]   for (i = 0; i < cred->ncerts; i++)
]     {
]       /* find one compatible certificate
]        */
]       if (requested_algo == GNUTLS_PK_ANY ||
]           requested_algo == cred->cert_list[i][0].subject_pk_algorithm)
]         {
]           /* if cert type and signature algorithm matches
]            */
]           /* *INDENT-OFF* */
]           if (session->security_parameters.cert_type
]               == cred->cert_list[i][0].cert_type
]               && (cred->cert_list[i][0].cert_type == GNUTLS_CRT_OPENPGP
]                   ||    /* FIXME: make this a check for certificate
]                            type capabilities */
]                   !_gnutls_version_has_selectable_sighash
]                   (gnutls_protocol_get_version (session))
]                   ||
]                   _gnutls_session_sign_algo_requested
]                   (session, cred->cert_list[i][0].sign_algo) == 0))
]             {
]               idx = i;
]               break;
]             }
]           /* *INDENT-ON* */
]         }
]     }

requested_algo was PK_ANY, cert_type X509, that part was uninteresting.
_gnutls_version_has_selectable_sighash() is TRUE iff we are doing TLS1.2; ah!
_gnutls_session_sign_algo_requested() looks at whether the client actually
requested a particular signature algorithm to go with that connection; of
course it didn't. So we fall back to an "agreeable default":

]     /* extension not received allow SHA1 and SHA256 */
]     hash = _gnutls_sign_get_hash_algorithm (sig);
]     if (hash == GNUTLS_DIG_SHA1 || hash == GNUTLS_DIG_SHA256)
]       return 0;

Better not be an early adopter and create certificates with SHA512...
downgraded the certificate's hash algorithm, and it works flawlessly again.

This error message "Insufficient credentials for that request" *really* has
to go away or to be replaced with something more meaningful. Calling this
"misleading" is still euphemistic...


Jan



More information about the Pkg-gnutls-maint mailing list