Closed dennisjackson closed 4 months ago
I should add that Cloudflare's fork of crypto/tls has ECH support in case that's of interest to the official Golang maintainers.
CC @golang/security
We were just talking about this today. It seems like a reasonable thing to implement given the direction the ecosystem is going. I think we're likely to prioritize client support first, but given the existence of stuff like Caddy, server support also seems reasonable.
I think we'll want to design the API such that we can internally wire up the net/http client to automatically populate the necessary information via e.g. the DNS discovery mechanism (or manually configure it by passing a tls.Config).
Thank you Roland :grin: Thousands of users appreciate that!
Any updates?
Is there work being done somewhere on this proposal or will start working on this proposal after ECH has been fully standardized to RFC?
I think ideally we'd like to get at least the client half of this in for 1.23, but we still need to decide on what the API will look like.
To just throw something out there, perhaps a very simple first option, which would support clients and leave the door open for sever support, would be to just add a field to tls.Config containing an already serialized ECHConfigList.
e.g.
type Config struct {
...
// EncryptedClientHelloConfigList is a serialized ECHConfigList. If
// provided, clients will attempt to connect to servers using Encrypted
// Client Hello (ECH) using one of the provided ECHConfigs. Servers
// currently ignore this field.
EncryptedClientHelloConfigList []byte
}
A client that populates this would then populate Config.ServerName as usual, and the internals would take care of the rest. One open question is how it would handle ECH failures, i.e. do we want to offer a knob to control whether we allow fallback or not (I would default to just failing closed, but others might have strong opinions on this).
This would hide away most of the internals of the ECH configuration, allowing direct passthrough for supported discovery mechanisms, and allow us to be as opinionated as we want in terms of picking HPKE cipher suites and such (which is generally a goal of crypto/tls).
For server support we'd then either reuse the EncryptedClientHelloConfigList field with an additional field for private keys, or a map between ECHConfig and private keys.
I have some questions that I don't know about:
Let's make this proposal about the client side, which the discussion has focused on, and we can revisit the server part in a separate proposal when we have ideas about what the API looks like.
- is there an existing HPKE implementation in go?
- Not yet. I suspect we'll use this as a learning experience to develop an internal-only HPKE API and then based on that experience propose a public one.
Actually, I saw on Wikipedia's article about Server Name Indication that cloudflare/go implemented ECH support in this commit from July, last year. This was merged on Feb 9th '24. You asked specifically about HPKE; I'm no expert, but there's a hpke.go file and a separate folder called hpke as well.
In the commit note, it does mention an external dependency requirement, to cloudflare/circl. That hpke folder looks like it is duplicated in the circl repository in fact.
Adds support for draft 13 of the Encrypted ClientHello (ECH) extension for TLS. This requires CIRCL to implement draft 08 or later of the HPKE specification (draft-irtf-cfrg-hpke-08).
Maybe cloudflare's licenses are compatible with golang's and their library could be merged into the standard library? It looks like a lot of work was put into that initial commit (38 changed files with 7,335 additions and 35 deletions)!
Maybe cloudflare's licenses are compatible with golang's and their library could be merged into the standard library?
FWIW, license compatibility is not enough; we require a CLA so that all code can be distributed under the simple Go license, not an amalgamation of many licenses.
This proposal has been added to the active column of the proposals project and will now be reviewed at the weekly proposal review meetings. — rsc for the proposal review group
Based on the discussion above, this proposal seems like a likely accept. — rsc for the proposal review group
The proposal details are in https://github.com/golang/go/issues/63369#issuecomment-1954915679.
No change in consensus, so accepted. 🎉 This issue now tracks the work of implementing the proposal. — rsc for the proposal review group
The proposal details are in https://github.com/golang/go/issues/63369#issuecomment-1954915679.
Change https://go.dev/cl/578575 mentions this issue: crypto/tls: add ech client support
Is there any hope for the server side part ? caddy really needs this feature and its authors defer to the standard library for an implementation..
Not for 1.23. We're planning on server support in 1.24.
When implementing this I realized we never defined the new error type in the proposal, and that we probably also want to introduce a ECHAccepted
bool field in the ConnectionState struct. Assuming there are no objections, I'm extending the proposal to include the following:
type ECHRejectionError struct {
RetryConfigList []byte
}
func (*ECHRejectionError) Error() string
type ConnectionState struct {
...
// ECHAccepted indicates if ECH was offered by the client, and accepted by the server.
ECHAccepted bool
}
One final change (I promise) which allows us to decouple outer server certificate verification vs inner certificate verification in the case of ECH rejection.
type Config {
...
// EncryptedClientHelloRejectionVerify, if not nil, is called when ECH is
// rejected, in order to verify the ECH provider certificate in the outer
// client hello. If it returns a non-nil error, the handshake is aborted and
// that error results.
//
// Unlike VerifyPeerCertificate and VerifyConnection, normal certificate
// verification will not be performed before calling
// EncryptedClientHelloRejectionVerify.
//
// If EncryptedClientHelloRejectionVerify is nil, and ECH is rejected the
// roots in RootCAs will be used to verify the ECH providers public
// certificate. VerifyPeerCertificate and VerifyConnection are not called
// when ECH is rejected, even if set.
EncryptedClientHelloRejectionVerify func(ConnectionState) error
}
It seems that this issue was changed from implementing ECH to solely implementing client side of ECH, where can one follow the progression of server side implementation? I can't find any issue or PR on it.
There isn't one yet. Once we're a bit deeper into the freeze I'll open an issue for tracking progress on it for 1.24.
@rolandshoemaker just as a heads up as I see no issue yet, did you create one?
Thanks for the nudge, filed #68500.
Encrypted Client Hello is a new privacy feature that is finishing standardization at the IETF. ECH is a big step forward for the internet, because it removes one of the last places where the websites users visit is leaked to the network in plaintext.
ECH has already been implemented in NSS and BoringSSL, and an experimental fork is available for OpenSSL.
Firefox has launched support for ECH, Chrome is expected to launch support imminently and Cloudflare have rolled out server-side support globally.
Support in crypto/tls would need to be both for servers and clients. Lack of support is currently blocking Caddy from shipping ECH.
cc @FiloSottile