New Upstream Release - golang-github-marten-seemann-qtls-go1-18
Ready changes
Summary
Merged new upstream version: 0.2.0 (was: 0.1.3).
Resulting package
Built on 2023-04-22T07:20 (took 5m15s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases golang-github-marten-seemann-qtls-go1-18-dev
Lintian Result
Diff
diff --git a/README.md b/README.md
index 3e90221..c592c4c 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# qtls
-[![Go Reference](https://pkg.go.dev/badge/github.com/marten-seemann/qtls-go1-17.svg)](https://pkg.go.dev/github.com/marten-seemann/qtls-go1-17)
-[![.github/workflows/go-test.yml](https://github.com/marten-seemann/qtls-go1-17/actions/workflows/go-test.yml/badge.svg)](https://github.com/marten-seemann/qtls-go1-17/actions/workflows/go-test.yml)
+[![Go Reference](https://pkg.go.dev/badge/github.com/quic-go/qtls-go1-18.svg)](https://pkg.go.dev/github.com/quic-go/qtls-go1-18)
+[![.github/workflows/go-test.yml](https://github.com/quic-go/qtls-go1-18/actions/workflows/go-test.yml/badge.svg)](https://github.com/quic-go/qtls-go1-18/actions/workflows/go-test.yml)
This repository contains a modified version of the standard library's TLS implementation, modified for the QUIC protocol. It is used by [quic-go](https://github.com/lucas-clemente/quic-go).
diff --git a/common.go b/common.go
index 4c9aeeb..3e4ced7 100644
--- a/common.go
+++ b/common.go
@@ -345,7 +345,8 @@ type clientSessionState struct {
// goroutines. Up to TLS 1.2, only ticket-based resumption is supported, not
// SessionID-based resumption. In TLS 1.3 they were merged into PSK modes, which
// are supported via this interface.
-//go:generate sh -c "mockgen -package qtls -destination mock_client_session_cache_test.go github.com/marten-seemann/qtls-go1-17 ClientSessionCache"
+//
+//go:generate sh -c "mockgen -package qtls -destination mock_client_session_cache_test.go github.com/quic-go/qtls-go1-18 ClientSessionCache"
type ClientSessionCache = tls.ClientSessionCache
// SignatureScheme is a tls.SignatureScheme
diff --git a/conn.go b/conn.go
index 31a87b5..2b8c730 100644
--- a/conn.go
+++ b/conn.go
@@ -32,6 +32,7 @@ type Conn struct {
// handshakeStatus is 1 if the connection is currently transferring
// application data (i.e. is not currently processing a handshake).
+ // handshakeStatus == 1 implies handshakeErr == nil.
// This field is only to be accessed with sync/atomic.
handshakeStatus uint32
// constant after handshake; protected by handshakeMutex
@@ -124,6 +125,9 @@ type Conn struct {
used0RTT bool
tmp [16]byte
+
+ connStateMutex sync.Mutex
+ connState ConnectionStateWith0RTT
}
// Access to net.Conn methods.
@@ -1458,6 +1462,13 @@ func (c *Conn) HandshakeContext(ctx context.Context) error {
}
func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
+ // Fast sync/atomic-based exit if there is no handshake in flight and the
+ // last one succeeded without an error. Avoids the expensive context setup
+ // and mutex for most Read and Write calls.
+ if c.handshakeComplete() {
+ return nil
+ }
+
handshakeCtx, cancel := context.WithCancel(ctx)
// Note: defer this before starting the "interrupter" goroutine
// so that we can tell the difference between the input being canceled and
@@ -1516,25 +1527,25 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
if c.handshakeErr == nil && !c.handshakeComplete() {
c.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
}
+ if c.handshakeErr != nil && c.handshakeComplete() {
+ panic("tls: internal error: handshake returned an error but is marked successful")
+ }
return c.handshakeErr
}
// ConnectionState returns basic TLS details about the connection.
func (c *Conn) ConnectionState() ConnectionState {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
- return c.connectionStateLocked()
+ c.connStateMutex.Lock()
+ defer c.connStateMutex.Unlock()
+ return c.connState.ConnectionState
}
// ConnectionStateWith0RTT returns basic TLS details (incl. 0-RTT status) about the connection.
func (c *Conn) ConnectionStateWith0RTT() ConnectionStateWith0RTT {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
- return ConnectionStateWith0RTT{
- ConnectionState: c.connectionStateLocked(),
- Used0RTT: c.used0RTT,
- }
+ c.connStateMutex.Lock()
+ defer c.connStateMutex.Unlock()
+ return c.connState
}
func (c *Conn) connectionStateLocked() ConnectionState {
@@ -1565,6 +1576,15 @@ func (c *Conn) connectionStateLocked() ConnectionState {
return toConnectionState(state)
}
+func (c *Conn) updateConnectionState() {
+ c.connStateMutex.Lock()
+ defer c.connStateMutex.Unlock()
+ c.connState = ConnectionStateWith0RTT{
+ Used0RTT: c.used0RTT,
+ ConnectionState: c.connectionStateLocked(),
+ }
+}
+
// OCSPResponse returns the stapled OCSP response from the TLS server, if
// any. (Only valid for client connections.)
func (c *Conn) OCSPResponse() []byte {
diff --git a/debian/changelog b/debian/changelog
index c1abc02..fc83be0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+golang-github-marten-seemann-qtls-go1-18 (0.2.0-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Sat, 22 Apr 2023 07:15:36 -0000
+
golang-github-marten-seemann-qtls-go1-18 (0.1.1-2) unstable; urgency=medium
* Source-only upload for testing migration.
diff --git a/go.mod b/go.mod
index df3cdbb..705ce2b 100644
--- a/go.mod
+++ b/go.mod
@@ -1,4 +1,4 @@
-module github.com/marten-seemann/qtls-go1-18
+module github.com/quic-go/qtls-go1-18
go 1.18
diff --git a/handshake_client.go b/handshake_client.go
index ab691d5..a2a0eae 100644
--- a/handshake_client.go
+++ b/handshake_client.go
@@ -290,6 +290,7 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
c.config.ClientSessionCache.Put(cacheKey, toClientSessionState(hs.session))
}
+ c.updateConnectionState()
return nil
}
diff --git a/handshake_client_tls13.go b/handshake_client_tls13.go
index 0de59fc..09d602d 100644
--- a/handshake_client_tls13.go
+++ b/handshake_client_tls13.go
@@ -78,6 +78,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error {
if err := hs.processServerHello(); err != nil {
return err
}
+ c.updateConnectionState()
if err := hs.sendDummyChangeCipherSpec(); err != nil {
return err
}
@@ -90,6 +91,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error {
if err := hs.readServerCertificate(); err != nil {
return err
}
+ c.updateConnectionState()
if err := hs.readServerFinished(); err != nil {
return err
}
@@ -104,7 +106,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error {
}
atomic.StoreUint32(&c.handshakeStatus, 1)
-
+ c.updateConnectionState()
return nil
}
diff --git a/handshake_server.go b/handshake_server.go
index 2fe8284..a6519d7 100644
--- a/handshake_server.go
+++ b/handshake_server.go
@@ -132,6 +132,7 @@ func (hs *serverHandshakeState) handshake() error {
c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random)
atomic.StoreUint32(&c.handshakeStatus, 1)
+ c.updateConnectionState()
return nil
}
@@ -270,7 +271,7 @@ func (hs *serverHandshakeState) processClientHello() error {
hs.ecdheOk = supportsECDHE(c.config, hs.clientHello.supportedCurves, hs.clientHello.supportedPoints)
- if hs.ecdheOk {
+ if hs.ecdheOk && len(hs.clientHello.supportedPoints) > 0 {
// Although omitting the ec_point_formats extension is permitted, some
// old OpenSSL version will refuse to handshake if not present.
//
@@ -351,6 +352,13 @@ func supportsECDHE(c *config, supportedCurves []CurveID, supportedPoints []uint8
break
}
}
+ // Per RFC 8422, Section 5.1.2, if the Supported Point Formats extension is
+ // missing, uncompressed points are supported. If supportedPoints is empty,
+ // the extension must be missing, as an empty extension body is rejected by
+ // the parser. See https://go.dev/issue/49126.
+ if len(supportedPoints) == 0 {
+ supportsPointFormat = true
+ }
return supportsCurve && supportsPointFormat
}
diff --git a/handshake_server_test.go b/handshake_server_test.go
index 5a28c6a..5ab1fdd 100644
--- a/handshake_server_test.go
+++ b/handshake_server_test.go
@@ -281,7 +281,7 @@ func TestTLS12OnlyCipherSuites(t *testing.T) {
func TestTLSPointFormats(t *testing.T) {
// Test that a Server returns the ec_point_format extension when ECC is
- // negotiated, and not returned on RSA handshake.
+ // negotiated, and not on a RSA handshake or if ec_point_format is missing.
tests := []struct {
name string
cipherSuites []uint16
@@ -289,8 +289,11 @@ func TestTLSPointFormats(t *testing.T) {
supportedPoints []uint8
wantSupportedPoints bool
}{
- {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{compressionNone}, true},
+ {"ECC", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{pointFormatUncompressed}, true},
+ {"ECC without ec_point_format", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, nil, false},
+ {"ECC with extra values", []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, []CurveID{CurveP256}, []uint8{13, 37, pointFormatUncompressed, 42}, true},
{"RSA", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, nil, false},
+ {"RSA with ec_point_format", []uint16{TLS_RSA_WITH_AES_256_GCM_SHA384}, nil, []uint8{pointFormatUncompressed}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -330,18 +333,8 @@ func TestTLSPointFormats(t *testing.T) {
t.Fatalf("didn't get ServerHello message in reply. Got %v\n", reply)
}
if tt.wantSupportedPoints {
- if len(serverHello.supportedPoints) < 1 {
- t.Fatal("missing ec_point_format extension from server")
- }
- found := false
- for _, p := range serverHello.supportedPoints {
- if p == pointFormatUncompressed {
- found = true
- break
- }
- }
- if !found {
- t.Fatal("missing uncompressed format in ec_point_format extension from server")
+ if !bytes.Equal(serverHello.supportedPoints, []uint8{pointFormatUncompressed}) {
+ t.Fatal("incorrect ec_point_format extension from server")
}
} else {
if len(serverHello.supportedPoints) != 0 {
@@ -1579,6 +1572,7 @@ func TestSNIGivenOnFailure(t *testing.T) {
t.Error("No error reported from server")
}
+ hs.c.updateConnectionState()
cs := hs.c.ConnectionState()
if cs.HandshakeComplete {
t.Error("Handshake registered as complete")
diff --git a/handshake_server_tls13.go b/handshake_server_tls13.go
index d26deb8..7ce09c3 100644
--- a/handshake_server_tls13.go
+++ b/handshake_server_tls13.go
@@ -53,6 +53,7 @@ func (hs *serverHandshakeStateTLS13) handshake() error {
if err := hs.checkForResumption(); err != nil {
return err
}
+ c.updateConnectionState()
if err := hs.pickCertificate(); err != nil {
return err
}
@@ -75,12 +76,13 @@ func (hs *serverHandshakeStateTLS13) handshake() error {
if err := hs.readClientCertificate(); err != nil {
return err
}
+ c.updateConnectionState()
if err := hs.readClientFinished(); err != nil {
return err
}
atomic.StoreUint32(&c.handshakeStatus, 1)
-
+ c.updateConnectionState()
return nil
}
@@ -777,6 +779,7 @@ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error {
if err != nil {
return err
}
+
if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
return err
}
diff --git a/mock_client_session_cache_test.go b/mock_client_session_cache_test.go
index 38d62e6..6988cb8 100644
--- a/mock_client_session_cache_test.go
+++ b/mock_client_session_cache_test.go
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: github.com/marten-seemann/qtls-go1-17 (interfaces: ClientSessionCache)
+// Source: github.com/quic-go/qtls-go1-18 (interfaces: ClientSessionCache)
// Package qtls is a generated GoMock package.
package qtls
diff --git a/record_layer_test.go b/record_layer_test.go
index 9bd0664..2b3877a 100644
--- a/record_layer_test.go
+++ b/record_layer_test.go
@@ -74,149 +74,184 @@ func TestAlternativeRecordLayer(t *testing.T) {
cOut := make(chan interface{}, 10)
defer close(cOut)
- serverEvents := make(chan interface{}, 100)
+ testConfig := testConfig.Clone()
+ testConfig.NextProtos = []string{"alpn"}
+
+ // server side
+ errChan := make(chan error)
+ serverConn := Server(
+ &unusedConn{},
+ testConfig,
+ &ExtraConfig{AlternativeRecordLayer: &recordLayerWithKeys{in: sIn, out: sOut}},
+ )
+ go func() {
+ defer serverConn.Close()
+ err := serverConn.Handshake()
+ connState := serverConn.ConnectionState()
+ if !connState.HandshakeComplete {
+ t.Fatal("expected the handshake to have completed")
+ }
+ errChan <- err
+ }()
+ serverKeyChan := make(chan *exportedKey, 4) // see server loop for the order in which keys are provided
go func() {
+ var counter int
for {
c, ok := <-sOut
if !ok {
return
}
- serverEvents <- c
+ switch counter {
+ case 0:
+ if c.([]byte)[0] != typeServerHello {
+ t.Errorf("expected ServerHello")
+ }
+ connState := serverConn.ConnectionState()
+ if connState.HandshakeComplete {
+ t.Error("didn't expect the handshake to be complete yet")
+ }
+ if connState.Version != VersionTLS13 {
+ t.Errorf("expected TLS 1.3, got %x", connState.Version)
+ }
+ if connState.NegotiatedProtocol == "" {
+ t.Error("expected ALPN to be negotiated")
+ }
+ case 1:
+ keyEv := c.(*exportedKey)
+ if keyEv.typ != "read" || keyEv.encLevel != EncryptionHandshake {
+ t.Errorf("expected the handshake read key")
+ }
+ serverKeyChan <- keyEv
+ case 2:
+ keyEv := c.(*exportedKey)
+ if keyEv.typ != "write" || keyEv.encLevel != EncryptionHandshake {
+ t.Errorf("expected the handshake write key")
+ }
+ serverKeyChan <- keyEv
+ case 3:
+ if c.([]byte)[0] != typeEncryptedExtensions {
+ t.Errorf("expected EncryptedExtensions")
+ }
+ case 4:
+ if c.([]byte)[0] != typeCertificate {
+ t.Errorf("expected Certificate")
+ }
+ case 5:
+ if c.([]byte)[0] != typeCertificateVerify {
+ t.Errorf("expected CertificateVerify")
+ }
+ case 6:
+ if c.([]byte)[0] != typeFinished {
+ t.Errorf("expected Finished")
+ }
+ case 7:
+ keyEv := c.(*exportedKey)
+ if keyEv.typ != "write" || keyEv.encLevel != EncryptionApplication {
+ t.Errorf("expected the application write key")
+ }
+ serverKeyChan <- keyEv
+ case 8:
+ keyEv := c.(*exportedKey)
+ if keyEv.typ != "read" || keyEv.encLevel != EncryptionApplication {
+ t.Errorf("expected the application read key")
+ }
+ serverKeyChan <- keyEv
+ default:
+ t.Error("didn't expect any more events")
+ }
+ counter++
if b, ok := c.([]byte); ok {
cIn <- b
}
}
}()
- clientEvents := make(chan interface{}, 100)
+ // client side
+ clientConn := Client(
+ &unusedConn{},
+ testConfig,
+ &ExtraConfig{AlternativeRecordLayer: &recordLayerWithKeys{in: cIn, out: cOut}},
+ )
+ defer clientConn.Close()
go func() {
+ var counter int
for {
c, ok := <-cOut
if !ok {
return
}
- clientEvents <- c
+ switch counter {
+ case 0:
+ if c.([]byte)[0] != typeClientHello {
+ t.Errorf("expected ClientHello")
+ }
+ connState := clientConn.ConnectionState()
+ if connState.HandshakeComplete {
+ t.Error("didn't expect the handshake to be complete yet")
+ }
+ if len(connState.PeerCertificates) != 0 {
+ t.Error("didn't expect a certificate yet")
+ }
+ case 1:
+ keyEv := c.(*exportedKey)
+ if keyEv.typ != "write" || keyEv.encLevel != EncryptionHandshake {
+ t.Errorf("expected the handshake write key")
+ }
+ compareExportedKeys(t, <-serverKeyChan, keyEv)
+ case 2:
+ keyEv := c.(*exportedKey)
+ if keyEv.typ != "read" || keyEv.encLevel != EncryptionHandshake {
+ t.Errorf("expected the handshake read key")
+ }
+ compareExportedKeys(t, <-serverKeyChan, keyEv)
+ case 3:
+ keyEv := c.(*exportedKey)
+ if keyEv.typ != "read" || keyEv.encLevel != EncryptionApplication {
+ t.Errorf("expected the application read key")
+ }
+ compareExportedKeys(t, <-serverKeyChan, keyEv)
+ case 4:
+ if c.([]byte)[0] != typeFinished {
+ t.Errorf("expected Finished")
+ }
+ case 5:
+ keyEv := c.(*exportedKey)
+ if keyEv.typ != "write" || keyEv.encLevel != EncryptionApplication {
+ t.Errorf("expected the application write key")
+ }
+ compareExportedKeys(t, <-serverKeyChan, keyEv)
+ default:
+ t.Error("didn't expect any more events")
+ }
+ counter++
if b, ok := c.([]byte); ok {
sIn <- b
}
}
}()
- errChan := make(chan error)
- go func() {
- extraConf := &ExtraConfig{
- AlternativeRecordLayer: &recordLayerWithKeys{in: sIn, out: sOut},
- }
- tlsConn := Server(&unusedConn{}, testConfig, extraConf)
- defer tlsConn.Close()
- errChan <- tlsConn.Handshake()
- }()
-
- extraConf := &ExtraConfig{
- AlternativeRecordLayer: &recordLayerWithKeys{in: cIn, out: cOut},
- }
- tlsConn := Client(&unusedConn{}, testConfig, extraConf)
- defer tlsConn.Close()
- if err := tlsConn.Handshake(); err != nil {
+ if err := clientConn.Handshake(); err != nil {
t.Fatalf("Handshake failed: %s", err)
}
-
- // Handshakes completed. Now check that events were received in the correct order.
- var clientHandshakeReadKey, clientHandshakeWriteKey *exportedKey
- var clientApplicationReadKey, clientApplicationWriteKey *exportedKey
- for i := 0; i <= 5; i++ {
- ev := <-clientEvents
- switch i {
- case 0:
- if ev.([]byte)[0] != typeClientHello {
- t.Fatalf("expected ClientHello")
- }
- case 1:
- keyEv := ev.(*exportedKey)
- if keyEv.typ != "write" || keyEv.encLevel != EncryptionHandshake {
- t.Fatalf("expected the handshake write key")
- }
- clientHandshakeWriteKey = keyEv
- case 2:
- keyEv := ev.(*exportedKey)
- if keyEv.typ != "read" || keyEv.encLevel != EncryptionHandshake {
- t.Fatalf("expected the handshake read key")
- }
- clientHandshakeReadKey = keyEv
- case 3:
- keyEv := ev.(*exportedKey)
- if keyEv.typ != "read" || keyEv.encLevel != EncryptionApplication {
- t.Fatalf("expected the application read key")
- }
- clientApplicationReadKey = keyEv
- case 4:
- if ev.([]byte)[0] != typeFinished {
- t.Fatalf("expected Finished")
- }
- case 5:
- keyEv := ev.(*exportedKey)
- if keyEv.typ != "write" || keyEv.encLevel != EncryptionApplication {
- t.Fatalf("expected the application write key")
- }
- clientApplicationWriteKey = keyEv
- }
+ connState := clientConn.ConnectionState()
+ if !connState.HandshakeComplete {
+ t.Fatal("expected the handshake to have completed")
}
- if len(clientEvents) > 0 {
- t.Fatal("didn't expect any more client events")
+ if connState.Version != VersionTLS13 {
+ t.Errorf("expected TLS 1.3, got %x", connState.Version)
+ }
+ if len(connState.PeerCertificates) == 0 {
+ t.Fatal("expected the certificate to be set")
}
- for i := 0; i <= 8; i++ {
- ev := <-serverEvents
- switch i {
- case 0:
- if ev.([]byte)[0] != typeServerHello {
- t.Fatalf("expected ServerHello")
- }
- case 1:
- keyEv := ev.(*exportedKey)
- if keyEv.typ != "read" || keyEv.encLevel != EncryptionHandshake {
- t.Fatalf("expected the handshake read key")
- }
- compareExportedKeys(t, clientHandshakeWriteKey, keyEv)
- case 2:
- keyEv := ev.(*exportedKey)
- if keyEv.typ != "write" || keyEv.encLevel != EncryptionHandshake {
- t.Fatalf("expected the handshake write key")
- }
- compareExportedKeys(t, clientHandshakeReadKey, keyEv)
- case 3:
- if ev.([]byte)[0] != typeEncryptedExtensions {
- t.Fatalf("expected EncryptedExtensions")
- }
- case 4:
- if ev.([]byte)[0] != typeCertificate {
- t.Fatalf("expected Certificate")
- }
- case 5:
- if ev.([]byte)[0] != typeCertificateVerify {
- t.Fatalf("expected CertificateVerify")
- }
- case 6:
- if ev.([]byte)[0] != typeFinished {
- t.Fatalf("expected Finished")
- }
- case 7:
- keyEv := ev.(*exportedKey)
- if keyEv.typ != "write" || keyEv.encLevel != EncryptionApplication {
- t.Fatalf("expected the application write key")
- }
- compareExportedKeys(t, clientApplicationReadKey, keyEv)
- case 8:
- keyEv := ev.(*exportedKey)
- if keyEv.typ != "read" || keyEv.encLevel != EncryptionApplication {
- t.Fatalf("expected the application read key")
- }
- compareExportedKeys(t, clientApplicationWriteKey, keyEv)
+ select {
+ case <-time.After(500 * time.Millisecond):
+ t.Fatal("server timed out")
+ case err := <-errChan:
+ if err != nil {
+ t.Fatalf("server handshake failed: %s", err)
}
}
- if len(serverEvents) > 0 {
- t.Fatal("didn't expect any more server events")
- }
}
func TestErrorOnOldTLSVersions(t *testing.T) {
diff --git a/ticket.go b/ticket.go
index 006b8c1..81e8a52 100644
--- a/ticket.go
+++ b/ticket.go
@@ -11,6 +11,7 @@ import (
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
+ "encoding/binary"
"errors"
"io"
"time"
@@ -232,6 +233,20 @@ func (c *Conn) getSessionTicketMsg(appData []byte) (*newSessionTicketMsgTLS13, e
return nil, err
}
m.lifetime = uint32(maxSessionTicketLifetime / time.Second)
+
+ // ticket_age_add is a random 32-bit value. See RFC 8446, section 4.6.1
+ // The value is not stored anywhere; we never need to check the ticket age
+ // because 0-RTT is not supported.
+ ageAdd := make([]byte, 4)
+ _, err = c.config.rand().Read(ageAdd)
+ if err != nil {
+ return nil, err
+ }
+ m.ageAdd = binary.LittleEndian.Uint32(ageAdd)
+
+ // ticket_nonce, which must be unique per connection, is always left at
+ // zero because we only ever send one ticket per connection.
+
if c.extraConfig != nil {
m.maxEarlyData = c.extraConfig.MaxEarlyData
}
Debdiff
File lists identical (after any substitutions)
No differences were encountered in the control files