It seems clear from the history of filed issues that some users will experience minor disruptions when switching to TLS 1.3. For disruptive changes like that, we typically do one or more releases in which the new feature is opt-in, with a prominent announcement about when it will turn on by default. Then we do at least one release with the feature opt-out. (Past examples include HTTP/2, vendor directories, and modules.)
Especially given how central TLS is to so many Go users (any HTTPS client or server!), it seems like we should do that for TLS 1.3 too:
Following the HTTP/2 example my suggestion would be to use GODEBUG=tls13=1 for opt-in now, and GODEBUG=tls13=0 for opt-out later.
/cc @filosottile
Following the HTTP/2 example my suggestion would be to use GODEBUG=tls13=1 for opt-in now
That's fine as long as there's also a way to enable it in code. Via tls.Config somehow? (MaxVersion and MinVersion both seem wrong.) Or at least with os.Setenv at runtime, but that means crypto/tls would need to keep calling Getenv. New bool on tls.Config would be kinda unfortunate, but maybe?
Should this apply to RSA-PSS as well?
New bool on tls.Config would be kinda unfortunate, but maybe?
A perhaps less specific version could be Debug []string, e.g. tlsConfig.Debug = []string{"tls13=1"}. Then it can be reused for more on/off switches in future Go releases, and its behavior is consistent with GODEBUG.
MaxVersion feels wrong semantically, and in practice it would lock applications to TLS 1.3 when TLS 1.4 ever comes out. I'm worried that tlsConfig.Debug would be a slippery slope, we get requests all the time to add all kinds of knobs which are inconsistent with the simplicity goal of crypto/tls, and that would provide an extra avenue for them.
How about GODEBUG=tls13=1, read once per tls.Config? It would allow os.Setenv in code, it would probably have acceptable performance, and still let applications test canaries without modifying code. It would probably have to be inherited via GetConfigForClient if one os.Getenv per connection is unacceptable.
MaxVersion = 0xFFFF would be my vote. Or some other unused constant to mean MaxBeta.
But users likely wouldn't be able to reach all such configs so the environment way probably best if Setenv works.
Change https://golang.org/cl/160998 mentions this issue: crypto/tls: disable RSA-PSS in TLS 1.2
Change https://golang.org/cl/160997 mentions this issue: crypto/tls: make TLS 1.3 opt-in
CL 160997 just uses os.Getenv at every connection. On Unix it takes a brief lock but uses an internal view of the environment, so there is no syscall. On Windows it makes a syscall. We can test the performance before adding complexity the day before the RC.
Done for Go 1.12, milestoned to Go 1.13 to switch to opt-out.
I think it is worth to document how to use os.Setenv to set this environment variable.
I guess this might work
os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tls13=1")
But os.Setenv("GODEBUG", "tls13=1") will overwrite other GODEBUG like GODEBUG=http2server=0.
If some other goroutines are also setting GODEBUG, there can be a race condition.
Alternately, maybe using another env is better. And os.Setenv("GOTLS13", "1") is mostly OK.
According to https://github.com/golang/go/issues/13611
GODEBUG usage should also be documented in https://tip.golang.org/pkg/runtime/
@crvv, I sent https://go-review.googlesource.com/c/go/+/162360
Change https://golang.org/cl/163039 mentions this issue: [release-branch.go1.12] crypto/tls: don't select RSA-PSS for client certificates in TLS 1.2
Change https://golang.org/cl/163080 mentions this issue: Revert "crypto/tls: disable RSA-PSS in TLS 1.2"
Change https://golang.org/cl/163081 mentions this issue: crypto/tls: enable TLS 1.3 by default
Milestoned to 1.14 to remove the opt-out.
Change https://golang.org/cl/191999 mentions this issue: crypto/tls: remove TLS 1.3 opt-out
Most helpful comment
@crvv, I sent https://go-review.googlesource.com/c/go/+/162360