Re: [TLS] TLS 1.2 and hash agility for signatures

Bodo Moeller <> Tue, 06 March 2007 14:30 UTC

Return-path: <>
Received: from [] ( by with esmtp (Exim 4.43) id 1HOag7-0004Yk-Ps; Tue, 06 Mar 2007 09:30:11 -0500
Received: from [] ( by with esmtp (Exim 4.43) id 1HOag6-0004Yb-3i for; Tue, 06 Mar 2007 09:30:10 -0500
Received: from ([]) by with esmtp (Exim 4.43) id 1HOag5-0007J5-2o for; Tue, 06 Mar 2007 09:30:09 -0500
Received: from [] (helo=tau.invalid) by (node=mrelayeu8) with ESMTP (Nemesis), id 0ML31I-1HOafy1Trx-0000Hq; Tue, 06 Mar 2007 15:30:02 +0100
Received: by tau.invalid (Postfix, from userid 1000) id C0D7C1B323; Tue, 6 Mar 2007 15:30:01 +0100 (CET)
Date: Tue, 6 Mar 2007 15:30:01 +0100
From: Bodo Moeller <>
Subject: Re: [TLS] TLS 1.2 and hash agility for signatures
Message-ID: <20070306143001.GA19204@tau.invalid>
References: <>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <>
User-Agent: Mutt/1.5.9i
X-Provags-ID: login:2100a517a32aea841b51dac1f7c5a318
X-Provags-ID2: V01U2FsdGVkX1+pTkZJPpAP/mb6SEldaJg62Kmg6ysXvM04Rls GdPJT0mYAivVNgknPfjRUnEaxFGXErrW6FaEsx6qqkRiaGzk+o gZgJ7ee0E8JJhSnzs5seQ==
X-Spam-Score: 0.0 (/)
X-Scan-Signature: ce732c7d36989a1bd55104ba259c40a1
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: "This is the mailing list for the Transport Layer Security working group of the IETF." <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>

On Tue, Mar 06, 2007 at 01:01:42PM +0200, wrote:

> There's one area in TLS 1.2 that still doesn't give me a warm 
> fuzzy feeling that "yes, this is the way it should be done", and 
> that's the algorithm agility for signatures (in certificates and
> ClientKeyExchange/ServerKeyExchange messages).
> I'd like to get some more discussion about this, and fresh
> ideas on what's the best way to implement it in TLS 1.2.
> Some issues that don't yet seem right:
> 1) Asymmetry: The server sends its list of supported hashes in the
> CertificateRequest message, together with list of trusted CAs (DNs)
> and ClientCertificateTypes. The client sends the list of supported
> hashes in cert_hash_types extension, list of trusted CAs (DNs or
> hashes) in trusted_ca_keys extension, and there's no equivalent of
> ClientCertificateType.  In addition, we have the "cert_type" extension
> for non-X.509 certs (draft-ietf-tls-openpgp-keys).
> To make things worse, ClientCertificateTypes field seems quite
> redundant, since at this point we already know the ciphersuite, and
> that limits our choice (it doesn't make sense to request dss_sign
> certificate if you've already negotiated RSA ciphersuite). Or if it's
> not redundant, then we need more text in the spec explaining why not.

I don't think that there's anything wrong with using a DSA certificate
in an RSA ciphersuite.  The only cases where symmetry is required are
the fixed_dh certificate types (and, similarly, the fixed_ecdh
certificate types from RFC 4492), since in these the client
certificate is tied to the actual key exchange and client
authentication does not use the separate CertificateVerify message.

If both the client and the server support all of RSA and DSA and
ECDSA, then it might just happen to be the case that the server has an
RSA certificate, say, while the client has an ECDSA certificate.  So
you might see an RSA ciphersuite in the handshake, but the client
would still use ECDSA in the CertificateVerify.  (This scenario can
make quite a lot of sense in certain configurations: RSA signature
verification and RSA encryption are usually very easy to do for the
client, but ECDSA signing might be much faster than RSA signing.)

So it's quite useful if the server can indicate to the client what
kinds of signatures it can verify.

> Perhaps we can't avoid this asymmetry completely, but is there any way
> to make this a bit nicer? Perhaps remove the ClientCertificateTypes
> field in TLS 1.2, and use cert_hash_types extension also from server
> to client?
> 2) Wrong concept: instead of telling what hash algorithms we support
> we'd really like to tell what kinds of signatures we can verify.
> E.g. for RSA, we have at least three different schemes (PKCS#1 v1.5,
> PSS and ANSI X9.32), all of which can be used with different hashes.
> And we also have DSS and ECDSA.
> For TLS level signatures (ServerKeyExchange/CertificateVerify), some
> part of this is already determined by the ciphersuite's key exchange
> algorithm (e.g. RSA here means PKCS#1 v1.5; if someone wants to use
> RSA PSS we'd define new ciphersuites). But for certificates, the
> situation is not the same; we could have certificate containing RSA
> public key signed with DSS, or something.
> Should we have signature_schemes extension instead of cert_hash_types?
> (with values like rsa_pkcs15_sha256, dss_sha1, ecdsa_sha512, etc.)  
> Or separate lists for certificate signatures and signatures in TLS?

I don't think that there's anything basically wrong with using
ClientCertificateType.  The list of ClientCertificateType values alone
doesn't provide complete information since RSA might mean RSA PKCS#1
v1.5 with a limited selection of hash algorithms only, or might allow
much more flexibility.  Adding a list of HashType values, as you point
out, doesn't quite address this issue since there are more aspects
that can be varied than just the choice of hash algorithm.  (Also,
sometimes, different choices of hash algorithms might be available
with different signature algorithms.)  Also often (but not always)
it's the complete certificate chain that must be considered, i.e. not
just the CertificateVerify signature but additionally each and every
signature in the client's certificate chain up to some anchor that the
server is willing to rely on for verification purposes.  (Sometimes
the server might not need to validate the actual certificate chain, if
permissible client certificates have been made available for direct
verification without the computational overhead of a PKI.)

So things can be quite complicated.  I don't think, though, that we
really have to solve all of this in the TLS specification!

In practice, the most important part of the CertificateRequest message
is certificate_authorities, the list of distinguished names of
acceptable CAs.  If the client happens to pick a certificate using a
chain for which the server does not have an appropriate anchor, then
it does not matter at all if the server can handle the hash algorithm
(or even the signature algorithm) used by the client for the
CertificateVerify or not -- either way the server won't be able to use
the signature.  But if the client has a certificate signed by a CA
that the server is willing to rely on, then generally that CA's
policies will determine what signature algorithms (with what hash
algortihms, etc.) can be encountered in certificate chains.  This is
usually enough since, for obvious pragmatic reasons, CAs don't tend to
mix lots of different techniques in their certificate chains.  (It's
similar for the use of the signing key in the client's end-entity
certificate -- for the case of RSA, the TLS 1.2 draft quite
reasonably, yet somewhat problematically [see below], says that "the
same function (denoted Hash) must be used as was used to create the
signature for the client's certificate".)

So we could spend a lot of time on coming up with a detailed solutions
allowing a find-grained negotiation of signing algorithm details, but
I think we don't really have to do that.  Reality always could be more
complicated than what we foresee (a complete solution would, for
example, have to provide the server with means to specify the X.509
extensions that it can parse, lest the client use a certificate chain
that has to be rejected due to an unknown critical extension).  In
practice, a rather simple solution should work very well.

The list of ClientCertificateType values in the CertificateRequest may
be a useful hint.  Besides, it is very brief, and we've always had
this in the protocol; so there's no reason to throw this out.  Maybe
adding a list of HashType values (as the TLS 1.2 draft does) is
reasonable too, but I don't really see compelling reasons to do so.
An optional TLS extension mirroring the client's Cert Hash Types
extension would look quite appropriate to me (why use a different tool
for server-to-client communcation than for client-to-server
communication?) -- also to be interpreted as a hint, not a complete
specification of what the server can handle.

I don't really think we need signature_schemes in place of
cert_hash_types.  The rsa_sign client certificate type currently is
restricted to RSA PKCS#1 v1.5 signatures, and if there was demand to
use PSS, say, a separate client certificate type for RSA-PSS would be
reasonable.  But then in practice, a demand for PSS would probably
mean separate PKIs with end-entity certificates intended for PSS
signing anyway (it would be rather silly to use a single RSA key both
for PKCS#1 v1.5 and PSS signing), so maybe we shouldn't worry about
this too much.

> 3) Tying algorithm in ServerKeyExchange/CertificateVerify and
> certificate. The current spec says that for RSA, signatures in TLS
> (ServerKeyExchange and CertificateVerify) use the same hash as was
> used by the CA in the certificate.
> The idea itself is not wrong: if you're worried about using SHA-1,
> then it's much more important to use something better in certificates
> (usually long-lived) than in ServerKeyExchange/CertificateVerify
> (which include fresh nonces, and are verified only once immediately
> following signature generation -- so offline attacks don't count).
> However... what if the cert isn't signed with RSA? Or it's signed with
> RSA PSS? And is it OK to require the peer to parse its own certificate
> (something not previously required)? Perhaps we should decouple these?

Well, the client wouldn't really have to actively parse its own
certificate, just know what's in there.  That's additional data, just
like the secret key matching the certificate's public key is
additional data.

Arguably, the TLS specification should not make such strict rules for
the hash algorithm to be used during signing, though, because it's
very reasonable to assume that the client's end-entity certificate
would completely specify the client's signing algorithm, including the
hash algorithm to be used.  And this might not match the hash
algorithm used by the CA while signing the respective certificate, so
the rule in the TLS 1.2 draft might be incompatible with keys that
otherwise would be absolutely acceptable for use.  (E.g., the CA might
have a 4096-bit RSA key and use a 256-bit hash for certificates, but
issue certificates on 2048-bit keys intended for use with 224-bit
hashes.)  The algorithm given in SubjectPublicKey might be more
explicit than just an unspecific "rsaEncryption" and might fix the
hash algorithm; and even if the SubjectPublicKey does not reveal it,
the hash algorithm might be fixed.

> 4) RSA-specific text. It looks like much of the text (and whole
> cert_hash_types) is really specific to RSA ciphersuites, since the
> spec fixes SHA-1 for DSS, and RFC4492 specifies that for ECDSA, the
> hash is always SHA-1 unless otherwise specified by yet-unspecified
> extension in the certificate.
> It may not be possible to avoid RSA-specific text, but then it should
> be easy to see what parts are specific to RSA and what are not. And we
> should probably plan for hash agility in DSS as well?

Yes, limiting DSA to SHA-1 quite obviously has historic reasons -- or
qrather, reasons that hopefully *will* become historic soon when FIPS
186-3 (with support for the newer SHA variants) finally is released!

> Comments? I think we'd want something reasonably simple in the spec,
> but on the other hand, it should be technically coherent as well.
> I'm planning to sketch something before Prague, but any kinds
> of ideas (or alternative ways of looking at the problem) would
> be welcome...

My take is that it is very reasonable to describe quite many things as
"SHOULD"s only, since the ability to verify certificates depends on
PKIs and their policies anyway, and much of the responsibility can be
put there.  If a CA is willing to sign certificates that are hard to
verify and if a server is willing to accept a PKI relying on such a
CA, then why not let them do this?  Generally, this won't happen,
since CAs will take care to issue certificates that work well in the
intended environment.  We don't have to freeze all the details of this
in the TLS specification.

Probably the TLS 1.2 specification should say more about how the
individual methods for ClientVerify work, e.g., that rsa_sign strictly
means RSASSA-PKCS1-v1_5, or possibly that RSASSA-PKCS1-v1_5 is what
SHOULD be used for rsa_sign.  I think we should keep
ClientCertificateTypes in the CertificateRequest, but maybe remove the
HashType list from the CertificateRequest and instead offer a server
hello extension for this.  (There's a similar client hello extension,
so this would provide more consistency within the protocol.)

Fixing the hash to SHA-1 for DSA is bad.  (As an aside, indeed there
are some cases where the new TLS 1.2 draft correctly says "DSA"
instead of the incorrect "DSS" -- maybe this finally should be
corrected throughout the document; i.e., merely mention the "DSS"
terminology in a historical note.)  This SHA-1-only approach won't
work well when FIPS 186-3 is released, so we should prepare something
for the new SHAs.  (This affects both the ServerKeyExchange and the
CertificateVerify messages.)

Similarly, the rule that ties the hash used for RSA signing to the
hash used for the respective certificate's signature is problematic.
In both cases (ServerKeyExchange and CertificateVerify), the "Cert
Hash Types" extension could be turned into a more general "Signature
Hash Types" extension (both as a client-side extension and a
server-side extension) that also covers the signatures within TLS, not
just those appearing in certificates.  The "rsa" and "dsa" cases of
the Signature type probably should be equipped with HashType fields so
that signatures can be verified without having to guess!


TLS mailing list