aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2019-02-05 15:29:02 -0500
committerFilippo Valsorda <filippo@golang.org>2019-02-07 18:32:13 +0000
commit5d9bc60893d66073ca82eecee7c9800321535f52 (patch)
tree933ece15a617db8ddd34ff9dc21bf14114bfad9c
parent95e5b07cf5fdf3352f04f5557df38f22c55ce8e8 (diff)
downloadgo-5d9bc60893d66073ca82eecee7c9800321535f52.tar.gz
go-5d9bc60893d66073ca82eecee7c9800321535f52.zip
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: Russ Cox <rsc@golang.org>
-rw-r--r--doc/go1.12.html22
-rw-r--r--src/crypto/tls/common.go43
-rw-r--r--src/crypto/tls/tls_test.go49
3 files changed, 102 insertions, 12 deletions
diff --git a/doc/go1.12.html b/doc/go1.12.html
index 5cd35b94c4..0f076e379d 100644
--- a/doc/go1.12.html
+++ b/doc/go1.12.html
@@ -388,15 +388,25 @@ for {
<h3 id="tls_1_3">TLS 1.3</h3>
<p>
- Go 1.12 adds support in the <code>crypto/tls</code> package for TLS 1.3 as
- specified in <a href="https://www.rfc-editor.org/info/rfc8446">RFC 8446</a>.
+ Go 1.12 adds opt-in support for TLS 1.3 in the <code>crypto/tls</code> package as
+ 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
- <a href="/pkg/crypto/tls/#Config"><code>Config</code></a> will automatically negotiate
- TLS 1.3 if available. All TLS 1.2 features except <code>TLSUnique</code> in
+<p>
+ To negotiate TLS 1.3, make sure you do not set an explicit <code>MaxVersion</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>
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>
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
index 59d5507e1a..0b08700d83 100644
--- a/src/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -16,6 +16,7 @@ import (
"io"
"math/big"
"net"
+ "os"
"strings"
"sync"
"time"
@@ -775,11 +776,53 @@ func (c *Config) supportedVersions(isClient bool) []uint16 {
if isClient && v < VersionTLS10 {
continue
}
+ // TLS 1.3 is opt-in in Go 1.12.
+ if v == VersionTLS13 && !isTLS13Supported() {
+ continue
+ }
versions = append(versions, v)
}
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 {
supportedVersions := c.supportedVersions(isClient)
if len(supportedVersions) == 0 {
diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go
index 00bb6e4ef3..9c26769b09 100644
--- a/src/crypto/tls/tls_test.go
+++ b/src/crypto/tls/tls_test.go
@@ -18,10 +18,18 @@ import (
"os"
"reflect"
"strings"
+ "sync"
"testing"
"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-----
MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
@@ -1076,18 +1084,47 @@ func TestEscapeRoute(t *testing.T) {
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 {
- t.Fatalf("Handshake failed when support for TLS 1.3 was dropped: %v", err)
+ t.Fatalf("Handshake failed: %v", err)
}
- if ss.Version != VersionTLS12 {
- t.Errorf("Server negotiated version %x, expected %x", cs.Version, VersionTLS12)
+ if ss.Version != v {
+ t.Errorf("Server negotiated version %x, expected %x", cs.Version, v)
}
- if cs.Version != VersionTLS12 {
- t.Errorf("Client negotiated version %x, expected %x", cs.Version, VersionTLS12)
+ if cs.Version != v {
+ 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
// that Config doesn't own such as Certificates.
func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) {