Commit 5d9bc608 authored by Filippo Valsorda's avatar Filippo Valsorda

crypto/tls: make TLS 1.3 opt-in

Updates #30055

Change-Id: If68615c8e9daa4226125dcc6a6866f29f3cfeef1
Reviewed-on: https://go-review.googlesource.com/c/160997
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 95e5b07c
...@@ -388,15 +388,25 @@ for { ...@@ -388,15 +388,25 @@ for {
<h3 id="tls_1_3">TLS 1.3</h3> <h3 id="tls_1_3">TLS 1.3</h3>
<p> <p>
Go 1.12 adds support in the <code>crypto/tls</code> package for TLS 1.3 as Go 1.12 adds opt-in support for TLS 1.3 in the <code>crypto/tls</code> package as
specified in <a href="https://www.rfc-editor.org/info/rfc8446">RFC 8446</a>. specified by <a href="https://www.rfc-editor.org/info/rfc8446">RFC 8446</a>. It can
be enabled by adding the value <code>tls13=1</code> to the <code>GODEBUG</code>
environment variable. It will be enabled by default in Go 1.13.
</p>
Programs that did not set an explicit <code>MaxVersion</code> in <p>
<a href="/pkg/crypto/tls/#Config"><code>Config</code></a> will automatically negotiate To negotiate TLS 1.3, make sure you do not set an explicit <code>MaxVersion</code> in
TLS 1.3 if available. All TLS 1.2 features except <code>TLSUnique</code> in <a href="/pkg/crypto/tls/#Config"><code>Config</code></a> and run your program with
the environment variable <code>GODEBUG=tls13=1</code> set.
</p>
<p>
All TLS 1.2 features except <code>TLSUnique</code> in
<a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a> <a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>
and renegotiation are available in TLS 1.3 and provide equivalent or and renegotiation are available in TLS 1.3 and provide equivalent or
better security and performance. better security and performance. Note that even though TLS 1.3 is backwards
compatible with previous versions, certain legacy systems might not work
correctly when attempting to negotiate it.
</p> </p>
<p> <p>
......
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
"io" "io"
"math/big" "math/big"
"net" "net"
"os"
"strings" "strings"
"sync" "sync"
"time" "time"
...@@ -775,11 +776,53 @@ func (c *Config) supportedVersions(isClient bool) []uint16 { ...@@ -775,11 +776,53 @@ func (c *Config) supportedVersions(isClient bool) []uint16 {
if isClient && v < VersionTLS10 { if isClient && v < VersionTLS10 {
continue continue
} }
// TLS 1.3 is opt-in in Go 1.12.
if v == VersionTLS13 && !isTLS13Supported() {
continue
}
versions = append(versions, v) versions = append(versions, v)
} }
return versions return versions
} }
// tls13Support caches the result for isTLS13Supported.
var tls13Support struct {
sync.Once
cached bool
}
// isTLS13Supported returns whether the program opted into TLS 1.3 via
// GODEBUG=tls13=1. It's cached after the first execution.
func isTLS13Supported() bool {
tls13Support.Do(func() {
tls13Support.cached = goDebugString("tls13") == "1"
})
return tls13Support.cached
}
// goDebugString returns the value of the named GODEBUG key.
// GODEBUG is of the form "key=val,key2=val2".
func goDebugString(key string) string {
s := os.Getenv("GODEBUG")
for i := 0; i < len(s)-len(key)-1; i++ {
if i > 0 && s[i-1] != ',' {
continue
}
afterKey := s[i+len(key):]
if afterKey[0] != '=' || s[i:i+len(key)] != key {
continue
}
val := afterKey[1:]
for i, b := range val {
if b == ',' {
return val[:i]
}
}
return val
}
return ""
}
func (c *Config) maxSupportedVersion(isClient bool) uint16 { func (c *Config) maxSupportedVersion(isClient bool) uint16 {
supportedVersions := c.supportedVersions(isClient) supportedVersions := c.supportedVersions(isClient)
if len(supportedVersions) == 0 { if len(supportedVersions) == 0 {
......
...@@ -18,10 +18,18 @@ import ( ...@@ -18,10 +18,18 @@ import (
"os" "os"
"reflect" "reflect"
"strings" "strings"
"sync"
"testing" "testing"
"time" "time"
) )
func init() {
// TLS 1.3 is opt-in for Go 1.12, but we want to run most tests with it enabled.
// TestTLS13Switch below tests the disabled behavior. See Issue 30055.
tls13Support.Do(func() {}) // defuse the sync.Once
tls13Support.cached = true
}
var rsaCertPEM = `-----BEGIN CERTIFICATE----- var rsaCertPEM = `-----BEGIN CERTIFICATE-----
MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
...@@ -1076,18 +1084,47 @@ func TestEscapeRoute(t *testing.T) { ...@@ -1076,18 +1084,47 @@ func TestEscapeRoute(t *testing.T) {
VersionSSL30, VersionSSL30,
} }
ss, cs, err := testHandshake(t, testConfig, testConfig) expectVersion(t, testConfig, testConfig, VersionTLS12)
}
func expectVersion(t *testing.T, clientConfig, serverConfig *Config, v uint16) {
ss, cs, err := testHandshake(t, clientConfig, serverConfig)
if err != nil { if err != nil {
t.Fatalf("Handshake failed when support for TLS 1.3 was dropped: %v", err) t.Fatalf("Handshake failed: %v", err)
} }
if ss.Version != VersionTLS12 { if ss.Version != v {
t.Errorf("Server negotiated version %x, expected %x", cs.Version, VersionTLS12) t.Errorf("Server negotiated version %x, expected %x", cs.Version, v)
} }
if cs.Version != VersionTLS12 { if cs.Version != v {
t.Errorf("Client negotiated version %x, expected %x", cs.Version, VersionTLS12) t.Errorf("Client negotiated version %x, expected %x", cs.Version, v)
} }
} }
// TestTLS13Switch checks the behavior of GODEBUG=tls13=[0|1]. See Issue 30055.
func TestTLS13Switch(t *testing.T) {
defer func(savedGODEBUG string) {
os.Setenv("GODEBUG", savedGODEBUG)
}(os.Getenv("GODEBUG"))
os.Setenv("GODEBUG", "tls13=0")
tls13Support.Once = sync.Once{} // reset the cache
tls12Config := testConfig.Clone()
tls12Config.MaxVersion = VersionTLS12
expectVersion(t, testConfig, testConfig, VersionTLS12)
expectVersion(t, tls12Config, testConfig, VersionTLS12)
expectVersion(t, testConfig, tls12Config, VersionTLS12)
expectVersion(t, tls12Config, tls12Config, VersionTLS12)
os.Setenv("GODEBUG", "tls13=1")
tls13Support.Once = sync.Once{} // reset the cache
expectVersion(t, testConfig, testConfig, VersionTLS13)
expectVersion(t, tls12Config, testConfig, VersionTLS12)
expectVersion(t, testConfig, tls12Config, VersionTLS12)
expectVersion(t, tls12Config, tls12Config, VersionTLS12)
}
// Issue 28744: Ensure that we don't modify memory // Issue 28744: Ensure that we don't modify memory
// that Config doesn't own such as Certificates. // that Config doesn't own such as Certificates.
func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) { func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment