crypto/tls: persist the createdAt time when re-wrapping session tickets
Change-Id: I33fcde2d544943fb04c2599810cf7fb773aeba1f
Reviewed-on: https://go-review.googlesource.com/c/go/+/234483
Run-TryBot: Katie Hockman <katie@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go
index 313872c..de93e1b 100644
--- a/src/crypto/tls/handshake_client_test.go
+++ b/src/crypto/tls/handshake_client_test.go
@@ -980,7 +980,28 @@
if bytes.Equal(ticket, getTicket()) {
t.Fatal("new ticket wasn't provided after old ticket expired")
}
- testResumeState("FreshSessionTicket", true)
+
+ // Age the session ticket a bit at a time, but don't expire it.
+ d := 0 * time.Hour
+ for i := 0; i < 13; i++ {
+ d += 12 * time.Hour
+ serverConfig.Time = func() time.Time { return time.Now().Add(d) }
+ testResumeState("OldSessionTicket", true)
+ }
+ // Expire it (now a little more than 7 days) and make sure a full
+ // handshake occurs for TLS 1.2. Resumption should still occur for
+ // TLS 1.3 since the client should be using a fresh ticket sent over
+ // by the server.
+ d += 12 * time.Hour
+ serverConfig.Time = func() time.Time { return time.Now().Add(d) }
+ if version == VersionTLS13 {
+ testResumeState("ExpiredSessionTicket", true)
+ } else {
+ testResumeState("ExpiredSessionTicket", false)
+ }
+ if bytes.Equal(ticket, getTicket()) {
+ t.Fatal("new ticket wasn't provided after old ticket expired")
+ }
// Reset serverConfig to ensure that calling SetSessionTicketKeys
// before the serverConfig is used works.
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
index 6aacfa1..57fba10 100644
--- a/src/crypto/tls/handshake_server.go
+++ b/src/crypto/tls/handshake_server.go
@@ -75,13 +75,8 @@
if err := hs.establishKeys(); err != nil {
return err
}
- // ticketSupported is set in a resumption handshake if the
- // ticket from the client was encrypted with an old session
- // ticket key and thus a refreshed ticket should be sent.
- if hs.hello.ticketSupported {
- if err := hs.sendSessionTicket(); err != nil {
- return err
- }
+ if err := hs.sendSessionTicket(); err != nil {
+ return err
}
if err := hs.sendFinished(c.serverFinished[:]); err != nil {
return err
@@ -688,6 +683,9 @@
}
func (hs *serverHandshakeState) sendSessionTicket() error {
+ // ticketSupported is set in a resumption handshake if the
+ // ticket from the client was encrypted with an old session
+ // ticket key and thus a refreshed ticket should be sent.
if !hs.hello.ticketSupported {
return nil
}
@@ -695,6 +693,13 @@
c := hs.c
m := new(newSessionTicketMsg)
+ createdAt := uint64(c.config.time().Unix())
+ if hs.sessionState != nil {
+ // If this is re-wrapping an old key, then keep
+ // the original time it was created.
+ createdAt = hs.sessionState.createdAt
+ }
+
var certsFromClient [][]byte
for _, cert := range c.peerCertificates {
certsFromClient = append(certsFromClient, cert.Raw)
@@ -702,7 +707,7 @@
state := sessionState{
vers: c.vers,
cipherSuite: hs.suite.id,
- createdAt: uint64(c.config.time().Unix()),
+ createdAt: createdAt,
masterSecret: hs.masterSecret,
certificates: certsFromClient,
}