mirror of https://github.com/golang/go.git
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>
This commit is contained in:
parent
95e5b07cf5
commit
5d9bc60893
|
|
@ -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 (
|
||||||
"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 {
|
||||||
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 (
|
||||||
"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) {
|
||||||
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) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue