Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: crypto/tls: supported certificate types API #32426

tmthrgd opened this issue Jun 4, 2019 · 2 comments


Copy link

commented Jun 4, 2019

Presently there is no simple way to determine whether a client/connection will support a particular TLS certificate type from within a GetCertificate callback.

The logic within crypto/tls is complex, subtle and hard to reason with from without crypto/tls. With the addition of Ed25519 in CL 177698, this is now even harder to get right as there are now three distinct certificate types that may be supported: RSA, ECDSA and Ed25519.

What I'd like to propose is some addition to ClientHelloInfo that would allow the GetCertificate callback to determine which certificate types are supported by the client and server for the connection. I'm not sure what an appropriate API would look like, but perhaps a method (Supports(...) bool) or struct as a field (Supports struct { RSA, ECDSA, Ed25519 bool }) or added fields (SupportsRSA bool; SupportsECDSA bool; SupportsEd25519 bool) on ClientHelloInfo.

An incomplete implementation was added to acme/autocert in CL 114501. This is documented as differing from crypto/tls (see commit message), and could cause handshake failures if there isn't a mutually supported ECDSA cipher suite. I've also tried implementing this myself using just the information in ClientHelloInfo and it is entirely non-trivial[1].

It's impossible to correctly implement this safely without support from crypto/tls because it's dependant on the configured/default cipher suites (which aren't always easily accessible) and internal crypto/tls implementation details.

This is useful for servers that might want to support several certificate types–to allow for older clients to successful connect–like acme/autocert does. For example the server may wish to prioritise Ed25519 over ECDSA and use RSA as a fallback, or more simply prefer ECDSA over RSA.

I'm not sure whether this will conflict with the recently approved proposal for #28660 (#28660 (comment)), but it's likely that will need to be considered.

[1]: To successfully negotiate an ECDSA certificate, you need a valid point format (uncompressed), a mutually supported curve, a mutually supported ECDSA cipher suite or support for TLS 1.3, and a supported ECDSA signature scheme. I believe Ed25519 support is the same except for needing the Ed25519 signature scheme.

There's also the presently unsupported RSASSA-PSS algorithms with public key OID RSASSA-PSS block of signature schemes (rsa_pss_pss_*) for RSA certificates with RSA-PSS only public keys. I presume support for that could wind up in crypto/tls one-day. And finally the signature_algorithms_cert extension may be of relevance in some cases.

@gopherbot gopherbot added this to the Proposal milestone Jun 4, 2019
@gopherbot gopherbot added the Proposal label Jun 4, 2019

This comment has been minimized.

Copy link
Contributor Author

commented Jun 20, 2019

I'm not sure exactly what the protocol for proposals is, but cc @FiloSottile.


This comment has been minimized.

Copy link

commented Jul 11, 2019

I feel like the most future-proof and reusable API here would be

func (*ClientHelloInfo) SupportsCertificate(*Certificate) bool
func (*CertificateRequestInfo) SupportsCertificate(*Certificate) bool

I like this because the logic is getting more complex over time, I heard requests that would be fulfilled by this multiple times, and even the crypto/tls internals would benefit from this API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
4 participants
You can’t perform that action at this time.