]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/crypto/tls/handshake_server.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[gostls13.git] / src / crypto / tls / handshake_server.go
index 0e0856c2242a006401c5bf597bf9fd6cba4b932e..99e30b884566d4ad3ef1930cce5ae4cad2ae8a55 100644 (file)
@@ -15,6 +15,7 @@ import (
        "fmt"
        "io"
        "sync/atomic"
+       "time"
 )
 
 // serverHandshakeState contains details of a server handshake in progress.
@@ -36,10 +37,6 @@ type serverHandshakeState struct {
 
 // serverHandshake performs a TLS handshake as a server.
 func (c *Conn) serverHandshake() error {
-       // If this is the first server handshake, we generate a random key to
-       // encrypt the tickets with.
-       c.config.serverInitOnce.Do(func() { c.config.serverInit(nil) })
-
        clientHello, err := c.readClientHello()
        if err != nil {
                return err
@@ -71,19 +68,15 @@ func (hs *serverHandshakeState) handshake() error {
        c.buffering = true
        if hs.checkForResumption() {
                // The client has included a session ticket and so we do an abbreviated handshake.
+               c.didResume = true
                if err := hs.doResumeHandshake(); err != nil {
                        return err
                }
                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
@@ -95,7 +88,6 @@ func (hs *serverHandshakeState) handshake() error {
                if err := hs.readFinished(nil); err != nil {
                        return err
                }
-               c.didResume = true
        } else {
                // The client didn't include a session ticket, or it wasn't
                // valid so we do a full handshake.
@@ -142,16 +134,18 @@ func (c *Conn) readClientHello() (*clientHelloMsg, error) {
                return nil, unexpectedMessageError(clientHello, msg)
        }
 
+       var configForClient *Config
+       originalConfig := c.config
        if c.config.GetConfigForClient != nil {
                chi := clientHelloInfo(c, clientHello)
-               if newConfig, err := c.config.GetConfigForClient(chi); err != nil {
+               if configForClient, err = c.config.GetConfigForClient(chi); err != nil {
                        c.sendAlert(alertInternalError)
                        return nil, err
-               } else if newConfig != nil {
-                       newConfig.serverInitOnce.Do(func() { newConfig.serverInit(c.config) })
-                       c.config = newConfig
+               } else if configForClient != nil {
+                       c.config = configForClient
                }
        }
+       c.ticketKeys = originalConfig.ticketKeys(configForClient)
 
        clientVersions := clientHello.supportedVersions
        if len(clientHello.supportedVersions) == 0 {
@@ -314,6 +308,7 @@ func (hs *serverHandshakeState) pickCipherSuite() error {
                c.sendAlert(alertHandshakeFailure)
                return errors.New("tls: no cipher suite supported by both client and server")
        }
+       c.cipherSuite = hs.suite.id
 
        for _, id := range hs.clientHello.cipherSuites {
                if id == TLS_FALLBACK_SCSV {
@@ -368,6 +363,11 @@ func (hs *serverHandshakeState) checkForResumption() bool {
                return false
        }
 
+       createdAt := time.Unix(int64(hs.sessionState.createdAt), 0)
+       if c.config.time().Sub(createdAt) > maxSessionTicketLifetime {
+               return false
+       }
+
        // Never resume a session for a different TLS version.
        if c.vers != hs.sessionState.vers {
                return false
@@ -408,6 +408,7 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
        c := hs.c
 
        hs.hello.cipherSuite = hs.suite.id
+       c.cipherSuite = hs.suite.id
        // We echo the client's session ID in the ServerHello to let it know
        // that we're doing a resumption.
        hs.hello.sessionId = hs.clientHello.sessionId
@@ -426,6 +427,13 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
                return err
        }
 
+       if c.config.VerifyConnection != nil {
+               if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil {
+                       c.sendAlert(alertBadCertificate)
+                       return err
+               }
+       }
+
        hs.masterSecret = hs.sessionState.masterSecret
 
        return nil
@@ -550,6 +558,12 @@ func (hs *serverHandshakeState) doFullHandshake() error {
                        return err
                }
        }
+       if c.config.VerifyConnection != nil {
+               if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil {
+                       c.sendAlert(alertBadCertificate)
+                       return err
+               }
+       }
 
        // Get client key exchange
        ckx, ok := msg.(*clientKeyExchangeMsg)
@@ -675,6 +689,9 @@ func (hs *serverHandshakeState) readFinished(out []byte) error {
 }
 
 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
        }
@@ -682,6 +699,13 @@ func (hs *serverHandshakeState) sendSessionTicket() error {
        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)
@@ -689,6 +713,7 @@ func (hs *serverHandshakeState) sendSessionTicket() error {
        state := sessionState{
                vers:         c.vers,
                cipherSuite:  hs.suite.id,
+               createdAt:    createdAt,
                masterSecret: hs.masterSecret,
                certificates: certsFromClient,
        }
@@ -720,7 +745,6 @@ func (hs *serverHandshakeState) sendFinished(out []byte) error {
                return err
        }
 
-       c.cipherSuite = hs.suite.id
        copy(out, finished.verifyData)
 
        return nil
@@ -768,6 +792,19 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
                c.verifiedChains = chains
        }
 
+       c.peerCertificates = certs
+       c.ocspResponse = certificate.OCSPStaple
+       c.scts = certificate.SignedCertificateTimestamps
+
+       if len(certs) > 0 {
+               switch certs[0].PublicKey.(type) {
+               case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
+               default:
+                       c.sendAlert(alertUnsupportedCertificate)
+                       return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", certs[0].PublicKey)
+               }
+       }
+
        if c.config.VerifyPeerCertificate != nil {
                if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
                        c.sendAlert(alertBadCertificate)
@@ -775,20 +812,6 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
                }
        }
 
-       if len(certs) == 0 {
-               return nil
-       }
-
-       switch certs[0].PublicKey.(type) {
-       case *ecdsa.PublicKey, *rsa.PublicKey, ed25519.PublicKey:
-       default:
-               c.sendAlert(alertUnsupportedCertificate)
-               return fmt.Errorf("tls: client certificate contains an unsupported public key of type %T", certs[0].PublicKey)
-       }
-
-       c.peerCertificates = certs
-       c.ocspResponse = certificate.OCSPStaple
-       c.scts = certificate.SignedCertificateTimestamps
        return nil
 }