aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/tls
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/tls')
-rw-r--r--src/crypto/tls/conn.go11
-rw-r--r--src/crypto/tls/handshake_server_tls13.go14
2 files changed, 25 insertions, 0 deletions
diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go
index 969f357834..d0a2550cbc 100644
--- a/src/crypto/tls/conn.go
+++ b/src/crypto/tls/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
@@ -1396,6 +1397,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
@@ -1454,6 +1462,9 @@ 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
}
diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go
index 109ff7a01d..1b2bf4dcd3 100644
--- a/src/crypto/tls/handshake_server_tls13.go
+++ b/src/crypto/tls/handshake_server_tls13.go
@@ -10,6 +10,7 @@ import (
"crypto"
"crypto/hmac"
"crypto/rsa"
+ "encoding/binary"
"errors"
"hash"
"io"
@@ -745,6 +746,19 @@ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error {
}
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 = hs.c.config.rand().Read(ageAdd)
+ if err != nil {
+ return 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 _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
return err
}