]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.boringcrypto] all: merge master into dev.boringcrypto
authorFilippo Valsorda <filippo@golang.org>
Wed, 14 Nov 2018 20:30:58 +0000 (15:30 -0500)
committerFilippo Valsorda <filippo@golang.org>
Wed, 14 Nov 2018 20:30:58 +0000 (15:30 -0500)
Change-Id: I81b64fe503bf07b4d7bd823286b83e663b5c0f76

1  2 
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/reflect.go
src/cmd/link/internal/ld/lib.go
src/crypto/tls/cipher_suites.go
src/crypto/tls/common.go
src/crypto/tls/handshake_client.go
src/crypto/tls/handshake_client_tls13.go
src/crypto/tls/handshake_messages_test.go
src/crypto/tls/handshake_server.go
src/crypto/tls/handshake_server_tls13.go
src/go/build/deps_test.go

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 5f0cb6d22b7b4ce9a48d68fa3c9c23ade4900b7b,1a819cc32f9a1488dd21a1dc6ffeda5f43b640ef..0fb70ba3ef701bea10d3b8200dc8fd251b854570
@@@ -349,7 -449,7 +449,7 @@@ func (hs *clientHandshakeStateTLS13) re
        }
  
        // See RFC 8446, Section 4.4.3.
-       if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, hs.hello.supportedSignatureAlgorithms) {
 -      if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) {
++      if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) {
                c.sendAlert(alertIllegalParameter)
                return errors.New("tls: invalid certificate signature algorithm")
        }
index ce2b04344ce9098cc58cc478d93bb7489667ec78,21beb8ef2dec220e18d7888824ebfebb7f39d2f5..1f08f6ac0e22435ce584c13a08486a8981626886
@@@ -364,11 -386,17 +386,17 @@@ func (*certificateRequestMsgTLS13) Gene
                m.scts = true
        }
        if rand.Intn(10) > 5 {
 -              m.supportedSignatureAlgorithms = supportedSignatureAlgorithms
 +              m.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
        }
        if rand.Intn(10) > 5 {
 -              m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms
 +              m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms()
        }
+       if rand.Intn(10) > 5 {
+               m.certificateAuthorities = make([][]byte, 3)
+               for i := 0; i < 3; i++ {
+                       m.certificateAuthorities[i] = randomBytes(rand.Intn(10)+1, rand)
+               }
+       }
        return reflect.ValueOf(m)
  }
  
index 00ce49f4441dcf2d1039e433fc52b5744ce6e3dd,c3ab276724b7a12d6d42ded1c5d829b0542f79ec..d5a32879d0bd6da94b126774c72513199f317efa
@@@ -679,10 -706,13 +706,15 @@@ func (c *Conn) processCertsFromClient(c
                }
        }
  
+       if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {
+               c.sendAlert(alertBadCertificate)
+               return errors.New("tls: client didn't provide a certificate")
+       }
        if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
                opts := x509.VerifyOptions{
 +                      IsBoring: isBoringCertificate,
 +
                        Roots:         c.config.ClientCAs,
                        CurrentTime:   c.config.time(),
                        Intermediates: x509.NewCertPool(),
index 0000000000000000000000000000000000000000,17bac61e1933fe463a7b119d9ecde99f8cfa8331..ccbe045a688219455b55c361803fe95d663ce5bd
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,827 +1,827 @@@
 -              certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms
+ // Copyright 2018 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+ // license that can be found in the LICENSE file.
+ package tls
+ import (
+       "bytes"
+       "crypto"
+       "crypto/hmac"
+       "crypto/rsa"
+       "errors"
+       "fmt"
+       "hash"
+       "io"
+       "sync/atomic"
+       "time"
+ )
+ // maxClientPSKIdentities is the number of client PSK identities the server will
+ // attempt to validate. It will ignore the rest not to let cheap ClientHello
+ // messages cause too much work in session ticket decryption attempts.
+ const maxClientPSKIdentities = 5
+ type serverHandshakeStateTLS13 struct {
+       c               *Conn
+       clientHello     *clientHelloMsg
+       hello           *serverHelloMsg
+       sentDummyCCS    bool
+       usingPSK        bool
+       suite           *cipherSuiteTLS13
+       cert            *Certificate
+       sigAlg          SignatureScheme
+       earlySecret     []byte
+       sharedKey       []byte
+       handshakeSecret []byte
+       masterSecret    []byte
+       trafficSecret   []byte // client_application_traffic_secret_0
+       transcript      hash.Hash
+       clientFinished  []byte
+ }
+ func (hs *serverHandshakeStateTLS13) handshake() error {
+       c := hs.c
+       // For an overview of the TLS 1.3 handshake, see RFC 8446, Section 2.
+       if err := hs.processClientHello(); err != nil {
+               return err
+       }
+       if err := hs.checkForResumption(); err != nil {
+               return err
+       }
+       if err := hs.pickCertificate(); err != nil {
+               return err
+       }
+       c.buffering = true
+       if err := hs.sendServerParameters(); err != nil {
+               return err
+       }
+       if err := hs.sendServerCertificate(); err != nil {
+               return err
+       }
+       if err := hs.sendServerFinished(); err != nil {
+               return err
+       }
+       // Note that at this point we could start sending application data without
+       // waiting for the client's second flight, but the application might not
+       // expect the lack of replay protection of the ClientHello parameters.
+       if _, err := c.flush(); err != nil {
+               return err
+       }
+       if err := hs.readClientCertificate(); err != nil {
+               return err
+       }
+       if err := hs.readClientFinished(); err != nil {
+               return err
+       }
+       atomic.StoreUint32(&c.handshakeStatus, 1)
+       return nil
+ }
+ func (hs *serverHandshakeStateTLS13) processClientHello() error {
+       c := hs.c
+       hs.hello = new(serverHelloMsg)
+       // TLS 1.3 froze the ServerHello.legacy_version field, and uses
+       // supported_versions instead. See RFC 8446, sections 4.1.3 and 4.2.1.
+       hs.hello.vers = VersionTLS12
+       hs.hello.supportedVersion = c.vers
+       if len(hs.clientHello.supportedVersions) == 0 {
+               c.sendAlert(alertIllegalParameter)
+               return errors.New("tls: client used the legacy version field to negotiate TLS 1.3")
+       }
+       if len(hs.clientHello.compressionMethods) != 1 ||
+               hs.clientHello.compressionMethods[0] != compressionNone {
+               c.sendAlert(alertIllegalParameter)
+               return errors.New("tls: TLS 1.3 client supports illegal compression methods")
+       }
+       hs.hello.random = make([]byte, 32)
+       if _, err := io.ReadFull(c.config.rand(), hs.hello.random); err != nil {
+               c.sendAlert(alertInternalError)
+               return err
+       }
+       if len(hs.clientHello.secureRenegotiation) != 0 {
+               c.sendAlert(alertHandshakeFailure)
+               return errors.New("tls: initial handshake had non-empty renegotiation extension")
+       }
+       if hs.clientHello.earlyData {
+               return errors.New("tls: early data skipping not implemented") // TODO(filippo)
+       }
+       hs.hello.sessionId = hs.clientHello.sessionId
+       hs.hello.compressionMethod = compressionNone
+       var preferenceList, supportedList []uint16
+       if c.config.PreferServerCipherSuites {
+               preferenceList = defaultCipherSuitesTLS13()
+               supportedList = hs.clientHello.cipherSuites
+       } else {
+               preferenceList = hs.clientHello.cipherSuites
+               supportedList = defaultCipherSuitesTLS13()
+       }
+       for _, suiteID := range preferenceList {
+               hs.suite = mutualCipherSuiteTLS13(supportedList, suiteID)
+               if hs.suite != nil {
+                       break
+               }
+       }
+       if hs.suite == nil {
+               c.sendAlert(alertHandshakeFailure)
+               return errors.New("tls: no cipher suite supported by both client and server")
+       }
+       c.cipherSuite = hs.suite.id
+       hs.hello.cipherSuite = hs.suite.id
+       hs.transcript = hs.suite.hash.New()
+       // Pick the ECDHE group in server preference order, but give priority to
+       // groups with a key share, to avoid a HelloRetryRequest round-trip.
+       var selectedGroup CurveID
+       var clientKeyShare *keyShare
+ GroupSelection:
+       for _, preferredGroup := range c.config.curvePreferences() {
+               for _, ks := range hs.clientHello.keyShares {
+                       if ks.group == preferredGroup {
+                               selectedGroup = ks.group
+                               clientKeyShare = &ks
+                               break GroupSelection
+                       }
+               }
+               if selectedGroup != 0 {
+                       continue
+               }
+               for _, group := range hs.clientHello.supportedCurves {
+                       if group == preferredGroup {
+                               selectedGroup = group
+                               break
+                       }
+               }
+       }
+       if selectedGroup == 0 {
+               c.sendAlert(alertHandshakeFailure)
+               return errors.New("tls: no ECDHE curve supported by both client and server")
+       }
+       if clientKeyShare == nil {
+               if err := hs.doHelloRetryRequest(selectedGroup); err != nil {
+                       return err
+               }
+               clientKeyShare = &hs.clientHello.keyShares[0]
+       }
+       if _, ok := curveForCurveID(selectedGroup); selectedGroup != X25519 && !ok {
+               c.sendAlert(alertInternalError)
+               return errors.New("tls: CurvePreferences includes unsupported curve")
+       }
+       params, err := generateECDHEParameters(c.config.rand(), selectedGroup)
+       if err != nil {
+               c.sendAlert(alertInternalError)
+               return err
+       }
+       hs.hello.serverShare = keyShare{group: selectedGroup, data: params.PublicKey()}
+       hs.sharedKey = params.SharedKey(clientKeyShare.data)
+       if hs.sharedKey == nil {
+               c.sendAlert(alertIllegalParameter)
+               return errors.New("tls: invalid client key share")
+       }
+       return nil
+ }
+ func (hs *serverHandshakeStateTLS13) checkForResumption() error {
+       c := hs.c
+       if c.config.SessionTicketsDisabled {
+               return nil
+       }
+       modeOK := false
+       for _, mode := range hs.clientHello.pskModes {
+               if mode == pskModeDHE {
+                       modeOK = true
+                       break
+               }
+       }
+       if !modeOK {
+               return nil
+       }
+       if len(hs.clientHello.pskIdentities) != len(hs.clientHello.pskBinders) {
+               c.sendAlert(alertIllegalParameter)
+               return errors.New("tls: invalid or missing PSK binders")
+       }
+       if len(hs.clientHello.pskIdentities) == 0 {
+               return nil
+       }
+       for i, identity := range hs.clientHello.pskIdentities {
+               if i >= maxClientPSKIdentities {
+                       break
+               }
+               plaintext, _ := c.decryptTicket(identity.label)
+               if plaintext == nil {
+                       continue
+               }
+               sessionState := new(sessionStateTLS13)
+               if ok := sessionState.unmarshal(plaintext); !ok {
+                       continue
+               }
+               createdAt := time.Unix(int64(sessionState.createdAt), 0)
+               if c.config.time().Sub(createdAt) > maxSessionTicketLifetime {
+                       continue
+               }
+               // We don't check the obfuscated ticket age because it's affected by
+               // clock skew and it's only a freshness signal useful for shrinking the
+               // window for replay attacks, which don't affect us as we don't do 0-RTT.
+               pskSuite := cipherSuiteTLS13ByID(sessionState.cipherSuite)
+               if pskSuite == nil || pskSuite.hash != hs.suite.hash {
+                       continue
+               }
+               // PSK connections don't re-establish client certificates, but carry
+               // them over in the session ticket. Ensure the presence of client certs
+               // in the ticket is consistent with the configured requirements.
+               sessionHasClientCerts := len(sessionState.certificate.Certificate) != 0
+               needClientCerts := requiresClientCert(c.config.ClientAuth)
+               if needClientCerts && !sessionHasClientCerts {
+                       continue
+               }
+               if sessionHasClientCerts && c.config.ClientAuth == NoClientCert {
+                       continue
+               }
+               psk := hs.suite.expandLabel(sessionState.resumptionSecret, "resumption",
+                       nil, hs.suite.hash.Size())
+               hs.earlySecret = hs.suite.extract(psk, nil)
+               binderKey := hs.suite.deriveSecret(hs.earlySecret, resumptionBinderLabel, nil)
+               // Clone the transcript in case a HelloRetryRequest was recorded.
+               transcript := cloneHash(hs.transcript, hs.suite.hash)
+               if transcript == nil {
+                       c.sendAlert(alertInternalError)
+                       return errors.New("tls: internal error: failed to clone hash")
+               }
+               transcript.Write(hs.clientHello.marshalWithoutBinders())
+               pskBinder := hs.suite.finishedHash(binderKey, transcript)
+               if !hmac.Equal(hs.clientHello.pskBinders[i], pskBinder) {
+                       c.sendAlert(alertDecryptError)
+                       return errors.New("tls: invalid PSK binder")
+               }
+               if err := c.processCertsFromClient(sessionState.certificate); err != nil {
+                       return err
+               }
+               hs.hello.selectedIdentityPresent = true
+               hs.hello.selectedIdentity = uint16(i)
+               hs.usingPSK = true
+               c.didResume = true
+               return nil
+       }
+       return nil
+ }
+ // cloneHash uses the encoding.BinaryMarshaler and encoding.BinaryUnmarshaler
+ // interfaces implemented by standard library hashes to clone the state of in
+ // to a new instance of h. It returns nil if the operation fails.
+ func cloneHash(in hash.Hash, h crypto.Hash) hash.Hash {
+       // Recreate the interface to avoid importing encoding.
+       type binaryMarshaler interface {
+               MarshalBinary() (data []byte, err error)
+               UnmarshalBinary(data []byte) error
+       }
+       marshaler, ok := in.(binaryMarshaler)
+       if !ok {
+               return nil
+       }
+       state, err := marshaler.MarshalBinary()
+       if err != nil {
+               return nil
+       }
+       out := h.New()
+       unmarshaler, ok := out.(binaryMarshaler)
+       if !ok {
+               return nil
+       }
+       if err := unmarshaler.UnmarshalBinary(state); err != nil {
+               return nil
+       }
+       return out
+ }
+ func (hs *serverHandshakeStateTLS13) pickCertificate() error {
+       c := hs.c
+       // Only one of PSK and certificates are used at a time.
+       if hs.usingPSK {
+               return nil
+       }
+       // This implements a very simplistic certificate selection strategy for now:
+       // getCertificate delegates to the application Config.GetCertificate, or
+       // selects based on the server_name only. If the selected certificate's
+       // public key does not match the client signature_algorithms, the handshake
+       // is aborted. No attention is given to signature_algorithms_cert, and it is
+       // not passed to the application Config.GetCertificate. This will need to
+       // improve according to RFC 8446, sections 4.4.2.2 and 4.2.3.
+       certificate, err := c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
+       if err != nil {
+               c.sendAlert(alertInternalError)
+               return err
+       }
+       supportedAlgs := signatureSchemesForCertificate(certificate)
+       if supportedAlgs == nil {
+               c.sendAlert(alertInternalError)
+               return fmt.Errorf("tls: unsupported certificate key (%T)", certificate.PrivateKey)
+       }
+       // Pick signature scheme in client preference order, as the server
+       // preference order is not configurable.
+       for _, preferredAlg := range hs.clientHello.supportedSignatureAlgorithms {
+               if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) {
+                       hs.sigAlg = preferredAlg
+                       break
+               }
+       }
+       if hs.sigAlg == 0 {
+               c.sendAlert(alertHandshakeFailure)
+               return errors.New("tls: client doesn't support selected certificate")
+       }
+       hs.cert = certificate
+       return nil
+ }
+ // sendDummyChangeCipherSpec sends a ChangeCipherSpec record for compatibility
+ // with middleboxes that didn't implement TLS correctly. See RFC 8446, Appendix D.4.
+ func (hs *serverHandshakeStateTLS13) sendDummyChangeCipherSpec() error {
+       if hs.sentDummyCCS {
+               return nil
+       }
+       hs.sentDummyCCS = true
+       _, err := hs.c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
+       return err
+ }
+ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) error {
+       c := hs.c
+       // The first ClientHello gets double-hashed into the transcript upon a
+       // HelloRetryRequest. See RFC 8446, Section 4.4.1.
+       hs.transcript.Write(hs.clientHello.marshal())
+       chHash := hs.transcript.Sum(nil)
+       hs.transcript.Reset()
+       hs.transcript.Write([]byte{typeMessageHash, 0, 0, uint8(len(chHash))})
+       hs.transcript.Write(chHash)
+       helloRetryRequest := &serverHelloMsg{
+               vers:              hs.hello.vers,
+               random:            helloRetryRequestRandom,
+               sessionId:         hs.hello.sessionId,
+               cipherSuite:       hs.hello.cipherSuite,
+               compressionMethod: hs.hello.compressionMethod,
+               supportedVersion:  hs.hello.supportedVersion,
+               selectedGroup:     selectedGroup,
+       }
+       hs.transcript.Write(helloRetryRequest.marshal())
+       if _, err := c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal()); err != nil {
+               return err
+       }
+       if err := hs.sendDummyChangeCipherSpec(); err != nil {
+               return err
+       }
+       msg, err := c.readHandshake()
+       if err != nil {
+               return err
+       }
+       clientHello, ok := msg.(*clientHelloMsg)
+       if !ok {
+               c.sendAlert(alertUnexpectedMessage)
+               return unexpectedMessageError(clientHello, msg)
+       }
+       if len(clientHello.keyShares) != 1 || clientHello.keyShares[0].group != selectedGroup {
+               c.sendAlert(alertIllegalParameter)
+               return errors.New("tls: client sent invalid key share in second ClientHello")
+       }
+       if clientHello.earlyData {
+               c.sendAlert(alertIllegalParameter)
+               return errors.New("tls: client indicated early data in second ClientHello")
+       }
+       if illegalClientHelloChange(clientHello, hs.clientHello) {
+               c.sendAlert(alertIllegalParameter)
+               return errors.New("tls: client illegally modified second ClientHello")
+       }
+       hs.clientHello = clientHello
+       return nil
+ }
+ // illegalClientHelloChange returns whether the two ClientHello messages are
+ // different, with the exception of the changes allowed before and after a
+ // HelloRetryRequest. See RFC 8446, Section 4.1.2.
+ func illegalClientHelloChange(ch, ch1 *clientHelloMsg) bool {
+       if len(ch.supportedVersions) != len(ch1.supportedVersions) ||
+               len(ch.cipherSuites) != len(ch1.cipherSuites) ||
+               len(ch.supportedCurves) != len(ch1.supportedCurves) ||
+               len(ch.supportedSignatureAlgorithms) != len(ch1.supportedSignatureAlgorithms) ||
+               len(ch.supportedSignatureAlgorithmsCert) != len(ch1.supportedSignatureAlgorithmsCert) ||
+               len(ch.alpnProtocols) != len(ch1.alpnProtocols) {
+               return true
+       }
+       for i := range ch.supportedVersions {
+               if ch.supportedVersions[i] != ch1.supportedVersions[i] {
+                       return true
+               }
+       }
+       for i := range ch.cipherSuites {
+               if ch.cipherSuites[i] != ch1.cipherSuites[i] {
+                       return true
+               }
+       }
+       for i := range ch.supportedCurves {
+               if ch.supportedCurves[i] != ch1.supportedCurves[i] {
+                       return true
+               }
+       }
+       for i := range ch.supportedSignatureAlgorithms {
+               if ch.supportedSignatureAlgorithms[i] != ch1.supportedSignatureAlgorithms[i] {
+                       return true
+               }
+       }
+       for i := range ch.supportedSignatureAlgorithmsCert {
+               if ch.supportedSignatureAlgorithmsCert[i] != ch1.supportedSignatureAlgorithmsCert[i] {
+                       return true
+               }
+       }
+       for i := range ch.alpnProtocols {
+               if ch.alpnProtocols[i] != ch1.alpnProtocols[i] {
+                       return true
+               }
+       }
+       return ch.vers != ch1.vers ||
+               !bytes.Equal(ch.random, ch1.random) ||
+               !bytes.Equal(ch.sessionId, ch1.sessionId) ||
+               !bytes.Equal(ch.compressionMethods, ch1.compressionMethods) ||
+               ch.nextProtoNeg != ch1.nextProtoNeg ||
+               ch.serverName != ch1.serverName ||
+               ch.ocspStapling != ch1.ocspStapling ||
+               !bytes.Equal(ch.supportedPoints, ch1.supportedPoints) ||
+               ch.ticketSupported != ch1.ticketSupported ||
+               !bytes.Equal(ch.sessionTicket, ch1.sessionTicket) ||
+               ch.secureRenegotiationSupported != ch1.secureRenegotiationSupported ||
+               !bytes.Equal(ch.secureRenegotiation, ch1.secureRenegotiation) ||
+               ch.scts != ch1.scts ||
+               !bytes.Equal(ch.cookie, ch1.cookie) ||
+               !bytes.Equal(ch.pskModes, ch1.pskModes)
+ }
+ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
+       c := hs.c
+       hs.transcript.Write(hs.clientHello.marshal())
+       hs.transcript.Write(hs.hello.marshal())
+       if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil {
+               return err
+       }
+       if err := hs.sendDummyChangeCipherSpec(); err != nil {
+               return err
+       }
+       earlySecret := hs.earlySecret
+       if earlySecret == nil {
+               earlySecret = hs.suite.extract(nil, nil)
+       }
+       hs.handshakeSecret = hs.suite.extract(hs.sharedKey,
+               hs.suite.deriveSecret(earlySecret, "derived", nil))
+       clientSecret := hs.suite.deriveSecret(hs.handshakeSecret,
+               clientHandshakeTrafficLabel, hs.transcript)
+       c.in.setTrafficSecret(hs.suite, clientSecret)
+       serverSecret := hs.suite.deriveSecret(hs.handshakeSecret,
+               serverHandshakeTrafficLabel, hs.transcript)
+       c.out.setTrafficSecret(hs.suite, serverSecret)
+       err := c.config.writeKeyLog(keyLogLabelClientHandshake, hs.clientHello.random, clientSecret)
+       if err != nil {
+               c.sendAlert(alertInternalError)
+               return err
+       }
+       err = c.config.writeKeyLog(keyLogLabelServerHandshake, hs.clientHello.random, serverSecret)
+       if err != nil {
+               c.sendAlert(alertInternalError)
+               return err
+       }
+       encryptedExtensions := new(encryptedExtensionsMsg)
+       if len(hs.clientHello.alpnProtocols) > 0 {
+               if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
+                       encryptedExtensions.alpnProtocol = selectedProto
+                       c.clientProtocol = selectedProto
+               }
+       }
+       hs.transcript.Write(encryptedExtensions.marshal())
+       if _, err := c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()); err != nil {
+               return err
+       }
+       return nil
+ }
+ func (hs *serverHandshakeStateTLS13) requestClientCert() bool {
+       return hs.c.config.ClientAuth >= RequestClientCert && !hs.usingPSK
+ }
+ func (hs *serverHandshakeStateTLS13) sendServerCertificate() error {
+       c := hs.c
+       // Only one of PSK and certificates are used at a time.
+       if hs.usingPSK {
+               return nil
+       }
+       if hs.requestClientCert() {
+               // Request a client certificate
+               certReq := new(certificateRequestMsgTLS13)
+               certReq.ocspStapling = true
+               certReq.scts = true
 -              if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms) {
++              certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
+               if c.config.ClientCAs != nil {
+                       certReq.certificateAuthorities = c.config.ClientCAs.Subjects()
+               }
+               hs.transcript.Write(certReq.marshal())
+               if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil {
+                       return err
+               }
+       }
+       certMsg := new(certificateMsgTLS13)
+       certMsg.certificate = *hs.cert
+       certMsg.scts = hs.clientHello.scts && len(hs.cert.SignedCertificateTimestamps) > 0
+       certMsg.ocspStapling = hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0
+       hs.transcript.Write(certMsg.marshal())
+       if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
+               return err
+       }
+       certVerifyMsg := new(certificateVerifyMsg)
+       certVerifyMsg.hasSignatureAlgorithm = true
+       certVerifyMsg.signatureAlgorithm = hs.sigAlg
+       sigType := signatureFromSignatureScheme(hs.sigAlg)
+       sigHash, err := hashFromSignatureScheme(hs.sigAlg)
+       if sigType == 0 || err != nil {
+               // getCertificate returned a certificate incompatible with the
+               // ClientHello supported signature algorithms.
+               c.sendAlert(alertInternalError)
+               return err
+       }
+       h := sigHash.New()
+       writeSignedMessage(h, serverSignatureContext, hs.transcript)
+       signOpts := crypto.SignerOpts(sigHash)
+       if sigType == signatureRSAPSS {
+               signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash}
+       }
+       sig, err := hs.cert.PrivateKey.(crypto.Signer).Sign(c.config.rand(), h.Sum(nil), signOpts)
+       if err != nil {
+               c.sendAlert(alertInternalError)
+               return errors.New("tls: failed to sign handshake: " + err.Error())
+       }
+       certVerifyMsg.signature = sig
+       hs.transcript.Write(certVerifyMsg.marshal())
+       if _, err := c.writeRecord(recordTypeHandshake, certVerifyMsg.marshal()); err != nil {
+               return err
+       }
+       return nil
+ }
+ func (hs *serverHandshakeStateTLS13) sendServerFinished() error {
+       c := hs.c
+       finished := &finishedMsg{
+               verifyData: hs.suite.finishedHash(c.out.trafficSecret, hs.transcript),
+       }
+       hs.transcript.Write(finished.marshal())
+       if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil {
+               return err
+       }
+       // Derive secrets that take context through the server Finished.
+       hs.masterSecret = hs.suite.extract(nil,
+               hs.suite.deriveSecret(hs.handshakeSecret, "derived", nil))
+       hs.trafficSecret = hs.suite.deriveSecret(hs.masterSecret,
+               clientApplicationTrafficLabel, hs.transcript)
+       serverSecret := hs.suite.deriveSecret(hs.masterSecret,
+               serverApplicationTrafficLabel, hs.transcript)
+       c.out.setTrafficSecret(hs.suite, serverSecret)
+       err := c.config.writeKeyLog(keyLogLabelClientTraffic, hs.clientHello.random, hs.trafficSecret)
+       if err != nil {
+               c.sendAlert(alertInternalError)
+               return err
+       }
+       err = c.config.writeKeyLog(keyLogLabelServerTraffic, hs.clientHello.random, serverSecret)
+       if err != nil {
+               c.sendAlert(alertInternalError)
+               return err
+       }
+       c.ekm = hs.suite.exportKeyingMaterial(hs.masterSecret, hs.transcript)
+       // If we did not request client certificates, at this point we can
+       // precompute the client finished and roll the transcript forward to send
+       // session tickets in our first flight.
+       if !hs.requestClientCert() {
+               if err := hs.sendSessionTickets(); err != nil {
+                       return err
+               }
+       }
+       return nil
+ }
+ func (hs *serverHandshakeStateTLS13) shouldSendSessionTickets() bool {
+       if hs.c.config.SessionTicketsDisabled {
+               return false
+       }
+       // Don't send tickets the client wouldn't use. See RFC 8446, Section 4.2.9.
+       for _, pskMode := range hs.clientHello.pskModes {
+               if pskMode == pskModeDHE {
+                       return true
+               }
+       }
+       return false
+ }
+ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error {
+       c := hs.c
+       hs.clientFinished = hs.suite.finishedHash(c.in.trafficSecret, hs.transcript)
+       finishedMsg := &finishedMsg{
+               verifyData: hs.clientFinished,
+       }
+       hs.transcript.Write(finishedMsg.marshal())
+       if !hs.shouldSendSessionTickets() {
+               return nil
+       }
+       resumptionSecret := hs.suite.deriveSecret(hs.masterSecret,
+               resumptionLabel, hs.transcript)
+       m := new(newSessionTicketMsgTLS13)
+       var certsFromClient [][]byte
+       for _, cert := range c.peerCertificates {
+               certsFromClient = append(certsFromClient, cert.Raw)
+       }
+       state := sessionStateTLS13{
+               cipherSuite:      hs.suite.id,
+               createdAt:        uint64(c.config.time().Unix()),
+               resumptionSecret: resumptionSecret,
+               certificate: Certificate{
+                       Certificate:                 certsFromClient,
+                       OCSPStaple:                  c.ocspResponse,
+                       SignedCertificateTimestamps: c.scts,
+               },
+       }
+       var err error
+       m.label, err = c.encryptTicket(state.marshal())
+       if err != nil {
+               return err
+       }
+       m.lifetime = uint32(maxSessionTicketLifetime / time.Second)
+       if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
+               return err
+       }
+       return nil
+ }
+ func (hs *serverHandshakeStateTLS13) readClientCertificate() error {
+       c := hs.c
+       if !hs.requestClientCert() {
+               return nil
+       }
+       // If we requested a client certificate, then the client must send a
+       // certificate message. If it's empty, no CertificateVerify is sent.
+       msg, err := c.readHandshake()
+       if err != nil {
+               return err
+       }
+       certMsg, ok := msg.(*certificateMsgTLS13)
+       if !ok {
+               c.sendAlert(alertUnexpectedMessage)
+               return unexpectedMessageError(certMsg, msg)
+       }
+       hs.transcript.Write(certMsg.marshal())
+       if err := c.processCertsFromClient(certMsg.certificate); err != nil {
+               return err
+       }
+       if len(certMsg.certificate.Certificate) != 0 {
+               msg, err = c.readHandshake()
+               if err != nil {
+                       return err
+               }
+               certVerify, ok := msg.(*certificateVerifyMsg)
+               if !ok {
+                       c.sendAlert(alertUnexpectedMessage)
+                       return unexpectedMessageError(certVerify, msg)
+               }
+               // See RFC 8446, Section 4.4.3.
++              if !isSupportedSignatureAlgorithm(certVerify.signatureAlgorithm, supportedSignatureAlgorithms()) {
+                       c.sendAlert(alertIllegalParameter)
+                       return errors.New("tls: invalid certificate signature algorithm")
+               }
+               sigType := signatureFromSignatureScheme(certVerify.signatureAlgorithm)
+               sigHash, err := hashFromSignatureScheme(certVerify.signatureAlgorithm)
+               if sigType == 0 || err != nil {
+                       c.sendAlert(alertInternalError)
+                       return err
+               }
+               if sigType == signaturePKCS1v15 || sigHash == crypto.SHA1 {
+                       c.sendAlert(alertIllegalParameter)
+                       return errors.New("tls: invalid certificate signature algorithm")
+               }
+               h := sigHash.New()
+               writeSignedMessage(h, clientSignatureContext, hs.transcript)
+               if err := verifyHandshakeSignature(sigType, c.peerCertificates[0].PublicKey,
+                       sigHash, h.Sum(nil), certVerify.signature); err != nil {
+                       c.sendAlert(alertDecryptError)
+                       return errors.New("tls: invalid certificate signature")
+               }
+               hs.transcript.Write(certVerify.marshal())
+       }
+       // If we waited until the client certificates to send session tickets, we
+       // are ready to do it now.
+       if err := hs.sendSessionTickets(); err != nil {
+               return err
+       }
+       return nil
+ }
+ func (hs *serverHandshakeStateTLS13) readClientFinished() error {
+       c := hs.c
+       msg, err := c.readHandshake()
+       if err != nil {
+               return err
+       }
+       finished, ok := msg.(*finishedMsg)
+       if !ok {
+               c.sendAlert(alertUnexpectedMessage)
+               return unexpectedMessageError(finished, msg)
+       }
+       if !hmac.Equal(hs.clientFinished, finished.verifyData) {
+               c.sendAlert(alertDecryptError)
+               return errors.New("tls: invalid client finished hash")
+       }
+       c.in.setTrafficSecret(hs.suite, hs.trafficSecret)
+       return nil
+ }
Simple merge